]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common: create dout_emergency interface and use it
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Sat, 12 Feb 2011 17:56:03 +0000 (09:56 -0800)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Sat, 12 Feb 2011 19:02:12 +0000 (11:02 -0800)
Create the dout_emergency interface, which is safe to call from a signal
handler or from inside dout itself.

Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/common/DoutStreambuf.cc
src/common/DoutStreambuf.h
src/common/signal.cc

index e4c444d3eea16bb42a53d06b57443518c167ad8b..9c60f0e745e05f653f9ff672f5079221ad1da731 100644 (file)
@@ -35,6 +35,8 @@
 #define TIME_FMT_SZ 26
 
 ///////////////////////////// Globals /////////////////////////////
+extern DoutStreambuf <char> *_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<charT, traits>::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<charT, traits>::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<charT, traits>::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<charT, traits>::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<charT, traits>::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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_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<charT, traits>::_rotate_files(const std::string &base)
   return 0;
 }
 
+template <typename charT, typename traits>
+void DoutStreambuf<charT, traits>::
+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 <char>;
index fcd493535f7742798d24582c9fa0c36731683660..aa9c449decc141aebbf6da034e17f39f02966ccd 100644 (file)
@@ -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
index 1a4f4f2ee0dbf13eac5286679a4e4d88da98bb15..e79dc590f995822f9ca63917ac86fff925a16350 100644 (file)
@@ -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 <syslog.h>
-
 std::string signal_mask_to_str()
 {
   sigset_t old_sigset;