From: Colin Patrick McCabe Date: Sat, 12 Feb 2011 17:56:03 +0000 (-0800) Subject: common: create dout_emergency interface and use it X-Git-Tag: v0.25~122^2~10 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4f4306e230938bb9f09921c82a8bf82c0e92f89e;p=ceph.git common: create dout_emergency interface and use it Create the dout_emergency interface, which is safe to call from a signal handler or from inside dout itself. Signed-off-by: Colin McCabe --- diff --git a/src/common/DoutStreambuf.cc b/src/common/DoutStreambuf.cc index e4c444d3eea..9c60f0e745e 100644 --- a/src/common/DoutStreambuf.cc +++ b/src/common/DoutStreambuf.cc @@ -35,6 +35,8 @@ #define TIME_FMT_SZ 26 ///////////////////////////// Globals ///////////////////////////// +extern DoutStreambuf *_doss; + // TODO: get rid of this lock using thread-local storage extern Mutex _dout_lock; @@ -97,16 +99,6 @@ static inline int dout_prio_to_syslog_prio(int prio) return LOG_DEBUG; } -/* Complain about errors even without a logfile */ -static void primitive_log(const std::string &str) -{ - if (safe_write(STDERR_FILENO, str.c_str(), str.size())) { - // ignore errors - ; - } - syslog(LOG_USER | LOG_NOTICE, "%s", str.c_str()); -} - static std::string get_basename(const std::string &filename) { size_t last_slash = filename.find_last_of("/"); @@ -143,7 +135,7 @@ static int create_symlink(string oldpath, const string &newpath) ostringstream oss; oss << __func__ << ": failed to remove '" << newpath << "': " << cpp_strerror(err) << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return err; } } @@ -152,7 +144,7 @@ static int create_symlink(string oldpath, const string &newpath) ostringstream oss; oss << __func__ << ": failed to symlink(oldpath='" << oldpath << "', newpath='" << newpath << "'): " << cpp_strerror(err) << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return err; } } @@ -281,7 +273,7 @@ void DoutStreambuf::read_global_config() ostringstream oss; oss << "DoutStreambuf::read_global_config: can't understand " << "g_conf.log_to_stderr = " << g_conf.log_to_stderr << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); break; } } @@ -321,7 +313,7 @@ int DoutStreambuf::handle_pid_change() if (ret) { ostringstream oss; oss << __func__ << ": failed to (re)create instance symlink\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ret; } } @@ -332,7 +324,7 @@ int DoutStreambuf::handle_pid_change() if (ret) { ostringstream oss; oss << __func__ << ": failed to (re)create rank symlink\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ret; } } @@ -343,7 +335,7 @@ int DoutStreambuf::handle_pid_change() ostringstream oss; oss << __func__ << ": failed to rename '" << opath << "' to " << "'" << new_opath << "': " << cpp_strerror(err) << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return err; } @@ -369,7 +361,7 @@ int DoutStreambuf::create_rank_symlink(int n) ostringstream oss; oss << __func__ << ": failed to create rank symlink with n = " << n << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ret; } @@ -453,7 +445,7 @@ std::string DoutStreambuf::_calculate_opath() const int err = errno; ostringstream oss; oss << __func__ << ": error calling gethostname: " << cpp_strerror(err) << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ""; } ostringstream oss; @@ -487,7 +479,7 @@ int DoutStreambuf::_read_ofile_config() if (opath.empty()) { ostringstream oss; oss << __func__ << ": _calculate_opath failed.\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return 1; } @@ -503,7 +495,7 @@ int DoutStreambuf::_read_ofile_config() if (ret) { ostringstream oss; oss << __func__ << ": failed to rotate instance symlinks\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ret; } @@ -512,7 +504,7 @@ int DoutStreambuf::_read_ofile_config() if (ret) { ostringstream oss; oss << __func__ << ": failed to create instance symlink\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return ret; } } @@ -525,7 +517,7 @@ int DoutStreambuf::_read_ofile_config() ostringstream oss; oss << "failed to open log file '" << opath << "': " << cpp_strerror(err) << "\n"; - primitive_log(oss.str()); + dout_emergency(oss.str()); return err; } @@ -580,7 +572,7 @@ int DoutStreambuf::_rotate_files(const std::string &base) ostringstream ess; ess << __func__ << ": failed to unlink '" << path << "': " << cpp_strerror(err) << "\n"; - primitive_log(ess.str()); + dout_emergency(ess.str()); return err; } //*_dout << "---- " << getpid() << " removed " << path << " ----" @@ -595,7 +587,7 @@ int DoutStreambuf::_rotate_files(const std::string &base) ostringstream ess; ess << __func__ << ": failed to rename '" << path << "' to " << "'" << new_path << "': " << cpp_strerror(err) << "\n"; - primitive_log(ess.str()); + dout_emergency(ess.str()); return err; } // *_dout << "---- " << getpid() << " renamed " << path << " -> " @@ -605,5 +597,45 @@ int DoutStreambuf::_rotate_files(const std::string &base) return 0; } +template +void DoutStreambuf:: +dout_emergency_impl(const char * const str) const +{ + int len = strlen(str); + if (ofd >= 0) { + if (safe_write(ofd, str, len)) { + ; // ignore error code + } + } + if (flags & DOUTSB_FLAG_SYSLOG) { + syslog(LOG_USER | LOG_CRIT, "%s", str); + } +} + +/* This function may be called from a signal handler. + * This function may be called before dout has been initialized. + */ +void dout_emergency(const char * const str) +{ + int len = strlen(str); + if (safe_write(STDERR_FILENO, str, len)) { + // ignore errors + ; + } + if (safe_write(STDOUT_FILENO, str, len)) { + ; // ignore error code + } + /* Normally we would take the lock before even checking _doss, but since + * this is an emergency, we can't do that. */ + if (_doss) { + _doss->dout_emergency_impl(str); + } +} + +void dout_emergency(const std::string &str) +{ + dout_emergency(str.c_str()); +} + // Explicit template instantiation template class DoutStreambuf ; diff --git a/src/common/DoutStreambuf.h b/src/common/DoutStreambuf.h index fcd493535f7..aa9c449decc 100644 --- a/src/common/DoutStreambuf.h +++ b/src/common/DoutStreambuf.h @@ -79,6 +79,10 @@ protected: virtual int_type underflow(); private: + void dout_emergency_impl(const char * const str) const; + friend void dout_emergency(const char * const str); + friend void dout_emergency(const std::string &str); + void _clear_output_buffer(); std::string _calculate_opath() const; std::string _get_symlink_dir() const; @@ -100,4 +104,9 @@ private: std::string rsym_path; }; +// Secret evil interfaces for writing logs without taking the lock. +// DO NOT USE THESE unless you have a really good reason. +extern void dout_emergency(const char * const str); +extern void dout_emergency(const std::string &str); + #endif diff --git a/src/common/signal.cc b/src/common/signal.cc index 1a4f4f2ee0d..e79dc590f99 100644 --- a/src/common/signal.cc +++ b/src/common/signal.cc @@ -39,9 +39,11 @@ void install_sighandler(int signum, signal_handler_t handler, int flags) ret = sigaction(signum, &act, &oldact); if (ret != 0) { - *_dout << "install_sighandler: sigaction returned " << ret << " when " - << "trying to install a signal handler for " - << sys_siglist[signum] << "\n"; + char buf[1024]; + snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned " + "%d when trying to install a signal handler for %s\n", + ret, sys_siglist[signum]); + dout_emergency(buf); exit(1); } } @@ -59,30 +61,36 @@ static void handle_fatal_signal(int signum) // This code may itself trigger a SIGSEGV if the heap is corrupt. In that // case, SA_RESETHAND specifies that the default signal handler-- // presumably dump core-- will handle it. - *_dout << "*** Caught signal (" << sys_siglist[signum] << ") ***" - << std::endl; - *_dout << "in thread " << std::hex << pthread_self() << std::endl; + char buf[1024]; + snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n " + "in thread %p\n", sys_siglist[signum], (void*)pthread_self()); + dout_emergency(buf); + + // TODO: don't use an ostringstream here. It could call malloc(), which we + // don't want inside a signal handler. + // Also fix the backtrace code not to allocate memory. BackTrace bt(0); - bt.print(*_dout); - _dout->flush(); + ostringstream oss; + bt.print(oss); + dout_emergency(oss.str()); // Use default handler to dump core int ret = raise(signum); // Normally, we won't get here. If we do, something is very weird. if (ret) { - *_dout << "handle_fatal_signal: failed to re-raise signal " << signum - << std::endl; + snprintf(buf, sizeof(buf), "handle_fatal_signal: failed to re-raise " + "signal %d\n", signum); + dout_emergency(buf); } else { - *_dout << "handle_fatal_signal: default handler for signal " << signum - << " didn't terminate the process?" << std::endl; + snprintf(buf, sizeof(buf), "handle_fatal_signal: default handler for " + "signal %d didn't terminate the process?\n", signum); + dout_emergency(buf); } exit(1); } -#include - std::string signal_mask_to_str() { sigset_t old_sigset;