#define TIME_FMT_SZ 26
///////////////////////////// Globals /////////////////////////////
+extern DoutStreambuf <char> *_doss;
+
// TODO: get rid of this lock using thread-local storage
extern Mutex _dout_lock;
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("/");
ostringstream oss;
oss << __func__ << ": failed to remove '" << newpath << "': "
<< cpp_strerror(err) << "\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return err;
}
}
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;
}
}
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;
}
}
if (ret) {
ostringstream oss;
oss << __func__ << ": failed to (re)create instance symlink\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return ret;
}
}
if (ret) {
ostringstream oss;
oss << __func__ << ": failed to (re)create rank symlink\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return ret;
}
}
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;
}
ostringstream oss;
oss << __func__ << ": failed to create rank symlink with n = "
<< n << "\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return ret;
}
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;
if (opath.empty()) {
ostringstream oss;
oss << __func__ << ": _calculate_opath failed.\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return 1;
}
if (ret) {
ostringstream oss;
oss << __func__ << ": failed to rotate instance symlinks\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return ret;
}
if (ret) {
ostringstream oss;
oss << __func__ << ": failed to create instance symlink\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return ret;
}
}
ostringstream oss;
oss << "failed to open log file '" << opath << "': "
<< cpp_strerror(err) << "\n";
- primitive_log(oss.str());
+ dout_emergency(oss.str());
return err;
}
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 << " ----"
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 << " -> "
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>;
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);
}
}
// 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;