]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
msgr: move pidfile handling, signal handing out
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Fri, 25 Mar 2011 22:27:54 +0000 (15:27 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Fri, 25 Mar 2011 22:39:00 +0000 (15:39 -0700)
Move signal handling and pidfile writing out of the messenger and into
signal.cc and pidfile.cc, respectively.

(Try to) remove our pid file when we crash due to a fatal signal.

Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/Makefile.am
src/common/pidfile.cc [new file with mode: 0644]
src/common/pidfile.h [new file with mode: 0644]
src/common/signal.cc
src/msg/SimpleMessenger.cc

index 3b0ad569e5eb1633f02f0488f122fc6d8fde31a9..6e09dd5579b4c430b3245992dcd7f2d2ed3f3242 100644 (file)
@@ -606,7 +606,8 @@ libcommon_files = \
        common/version.cc \
        common/hex.cc \
        common/entity_name.cc \
-       common/ceph_crypto.cc
+       common/ceph_crypto.cc \
+       common/pidfile.cc
 
 if WITH_PROFILER
 libcommon_files += perfglue/cpu_profiler.cc
@@ -1052,7 +1053,8 @@ noinst_HEADERS = \
        tools/common.h\
        tools/gui.h\
        tools/gui_resources.h\
-       test/osd/RadosModel.h
+       test/osd/RadosModel.h\
+       common/pidfile.h
 
 all_sources = $(cmon_SOURCES) $(ceph_SOURCES) $(cephfs_SOURCES) $(librados_config_SOURCES) $(cauthtool_SOURCES) $(monmaptool_SOURCES) \
        $(crushtool_SOURCES) $(osdmaptool_SOURCES) $(cconf_SOURCES) $(mount_ceph_SOURCES) $(cmds_SOURCES) \
diff --git a/src/common/pidfile.cc b/src/common/pidfile.cc
new file mode 100644 (file)
index 0000000..9aeca9c
--- /dev/null
@@ -0,0 +1,93 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "common/errno.h"
+#include "common/pidfile.h"
+#include "common/safe_io.h"
+#include "debug.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define dout_prefix *_dout
+
+static char pid_file[PATH_MAX] = "";
+
+int pidfile_write(const md_config_t *conf)
+{
+  int ret, fd;
+
+  const char *pfile = conf->pid_file;
+  if ((pfile == NULL) || (!pfile[0])) {
+    return pidfile_remove();
+  }
+  strncpy(pid_file, pfile, PATH_MAX);
+
+  fd = TEMP_FAILURE_RETRY(::open(pid_file,
+                                O_CREAT|O_TRUNC|O_WRONLY, 0644));
+  if (fd < 0) {
+    int err = errno;
+    derr << "write_pid_file: failed to open pid file '"
+        << pid_file << "': " << cpp_strerror(err) << dendl;
+    return err;
+  }
+
+  char buf[20];
+  int len = snprintf(buf, sizeof(buf), "%d\n", getpid());
+  ret = safe_write(fd, buf, len);
+  if (ret < 0) {
+    derr << "write_pid_file: failed to write to pid file '"
+        << pid_file << "': " << cpp_strerror(ret) << dendl;
+    TEMP_FAILURE_RETRY(::close(fd));
+    return ret;
+  }
+  if (TEMP_FAILURE_RETRY(::close(fd))) {
+    ret = errno;
+    derr << "SimpleMessenger::write_pid_file: failed to close to pid file '"
+        << pid_file << "': " << cpp_strerror(ret) << dendl;
+    return -ret;
+  }
+
+  return 0;
+}
+
+int pidfile_remove(void)
+{
+  if (!pid_file[0])
+    return 0;
+
+  // only remove it if it has OUR pid in it!
+  int fd = TEMP_FAILURE_RETRY(::open(pid_file, O_RDONLY));
+  if (fd < 0)
+    return -errno;
+  char buf[32];
+  memset(buf, 0, sizeof(buf));
+  ssize_t res = safe_read(fd, buf, sizeof(buf));
+  if (res < 0)
+    return res;
+  TEMP_FAILURE_RETRY(::close(fd));
+  int a = atoi(buf);
+  if (a != getpid())
+    return -EDOM;
+
+  res = ::unlink(pid_file);
+  if (res)
+    return res;
+
+  pid_file[0] = '\0';
+  return 0;
+}
diff --git a/src/common/pidfile.h b/src/common/pidfile.h
new file mode 100644 (file)
index 0000000..c17741b
--- /dev/null
@@ -0,0 +1,28 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#ifndef CEPH_COMMON_PIDFILE_H
+#define CEPH_COMMON_PIDFILE_H
+
+class md_config_t;
+
+// Write a pidfile with the current pid, using the configuration in the
+// provided conf structure.
+int pidfile_write(const md_config_t *conf);
+
+// Remove the pid file that was previously written by pidfile_write.
+// This is safe to call in a signal handler context.
+int pidfile_remove(void);
+
+#endif
index 64886e149b63623b729f6dea44bb483163b59123..840876ec2b0112f91f7feca4118c107aa2fcc649 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "common/BackTrace.h"
 #include "common/ProfLogger.h"
+#include "common/pidfile.h"
 #include "common/debug.h"
 #include "common/signal.h"
 #include "common/config.h"
@@ -56,6 +57,37 @@ void sighup_handler(int signum)
   logger_reopen_all();
 }
 
+static void reraise_fatal(int signum)
+{
+  // Use default handler to dump core
+  int ret = raise(signum);
+
+  // Normally, we won't get here. If we do, something is very weird.
+  char buf[1024];
+  if (ret) {
+    snprintf(buf, sizeof(buf), "reraise_fatal: failed to re-raise "
+           "signal %d\n", signum);
+    dout_emergency(buf);
+  }
+  else {
+    snprintf(buf, sizeof(buf), "reraise_fatal: default handler for "
+           "signal %d didn't terminate the process?\n", signum);
+    dout_emergency(buf);
+  }
+  exit(1);
+}
+
+static void handle_shutdown_signal(int signum)
+{
+  char buf[1024];
+  snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
+           "in thread %p. Shutting down.\n",
+           sys_siglist[signum], (void*)pthread_self());
+  dout_emergency(buf);
+  pidfile_remove();
+  reraise_fatal(signum);
+}
+
 static void handle_fatal_signal(int signum)
 {
   // This code may itself trigger a SIGSEGV if the heap is corrupt. In that
@@ -65,6 +97,7 @@ static void handle_fatal_signal(int signum)
   snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
            "in thread %p\n", sys_siglist[signum], (void*)pthread_self());
   dout_emergency(buf);
+  pidfile_remove();
 
   // TODO: don't use an ostringstream here. It could call malloc(), which we
   // don't want inside a signal handler.
@@ -74,21 +107,7 @@ static void handle_fatal_signal(int signum)
   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) {
-    snprintf(buf, sizeof(buf), "handle_fatal_signal: failed to re-raise "
-           "signal %d\n", signum);
-    dout_emergency(buf);
-  }
-  else {
-    snprintf(buf, sizeof(buf), "handle_fatal_signal: default handler for "
-           "signal %d didn't terminate the process?\n", signum);
-    dout_emergency(buf);
-  }
-  exit(1);
+  reraise_fatal(signum);
 }
 
 std::string signal_mask_to_str()
@@ -122,6 +141,8 @@ void install_standard_sighandlers(void)
   install_sighandler(SIGXCPU, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
   install_sighandler(SIGXFSZ, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
   install_sighandler(SIGSYS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
+  install_sighandler(SIGTERM, handle_shutdown_signal, SA_RESETHAND | SA_NODEFER);
+  install_sighandler(SIGINT, handle_shutdown_signal, SA_RESETHAND | SA_NODEFER);
 }
 
 void block_signals(sigset_t *old_sigset, int *siglist)
index 467e5a05623a3b0f009189ae92aa5430788cfeb3..ac4d132daa923baf5fbdc9b333c1118f056fe7c0 100644 (file)
@@ -35,8 +35,8 @@
 
 #include "common/Timer.h"
 #include "common/errno.h"
+#include "common/pidfile.h"
 #include "common/safe_io.h"
-#include "common/signal.h"
 
 #define DOUT_SUBSYS ms
 #undef dout_prefix
@@ -2317,92 +2317,6 @@ int SimpleMessenger::rebind(int avoid_port)
   return accepter.rebind(avoid_port);
 }
 
-static void remove_pid_file(int in_signal_handler = 0)
-{
-  if (!g_conf.pid_file)
-    return;
-
-  // only remove it if it has OUR pid in it!
-  int fd = ::open(g_conf.pid_file, O_RDONLY);
-  if (fd < 0)
-    return;  // fail silently if there is no pid to remove
-
-  char buf[32];
-  memset(buf, 0, sizeof(buf));
-  if (TEMP_FAILURE_RETRY(::read(fd, buf, sizeof(buf)-1)) < 0) {
-    int err = errno;
-    if (!in_signal_handler) {
-      generic_dout(0) << "remove_pid_file: error reading " << g_conf.pid_file
-           << ": " << cpp_strerror(err) << dendl;
-    }
-    return;
-  }
-  TEMP_FAILURE_RETRY(::close(fd));
-
-  int a = atoi(buf);
-  if (a != getpid()) {
-    if (!in_signal_handler) {
-      generic_dout(0) << "remove_pid_file: strange, pid file " << g_conf.pid_file
-             << " has " << a << ", not expected " << getpid() << dendl;
-    }
-    return;
-  }
-
-  if (::unlink(g_conf.pid_file)) {
-    int err = errno;
-    if (!in_signal_handler) {
-      generic_dout(0) << "remove_pid_file: error unlinking " << g_conf.pid_file
-           << ": " << cpp_strerror(err) << dendl;
-    }
-    return;
-  }
-}
-
-static void handle_signal(int sig)
-{
-  remove_pid_file(sig);
-  signal(sig, SIG_DFL);
-  kill(getpid(), sig);
-}
-
-int SimpleMessenger::write_pid_file(int pid)
-{
-  int ret, fd;
-
-  if (!g_conf.pid_file)
-    return 0;
-
-  fd = TEMP_FAILURE_RETRY(::open(g_conf.pid_file,
-                                O_CREAT|O_TRUNC|O_WRONLY, 0644));
-  if (fd < 0) {
-    int err = errno;
-    derr << "SimpleMessenger::write_pid_file: failed to open pid file '"
-        << g_conf.pid_file << "': " << cpp_strerror(err) << dendl;
-    return err;
-  }
-
-  char buf[20];
-  int len = snprintf(buf, sizeof(buf), "%d\n", pid);
-  ret = safe_write(fd, buf, len);
-  if (ret < 0) {
-    derr << "SimpleMessenger::write_pid_file: failed to write to pid file '"
-        << g_conf.pid_file << "': " << cpp_strerror(ret) << dendl;
-    TEMP_FAILURE_RETRY(::close(fd));
-    return ret;
-  }
-  if (TEMP_FAILURE_RETRY(::close(fd))) {
-    ret = errno;
-    derr << "SimpleMessenger::write_pid_file: failed to close to pid file '"
-        << g_conf.pid_file << "': " << cpp_strerror(ret) << dendl;
-    return ret;
-  }
-
-  signal(SIGTERM, handle_signal);
-  signal(SIGINT, handle_signal);
-
-  return 0;
-}
-
 int SimpleMessenger::start(bool daemonize, uint64_t nonce)
 {
   // register at least one entity, first!
@@ -2435,7 +2349,7 @@ int SimpleMessenger::start(bool daemonize, uint64_t nonce)
     int r = daemon(1, 0);
     assert(r >= 0);
     install_standard_sighandlers();
-    write_pid_file(getpid());
+    pidfile_write(&g_conf);
  
     if (g_conf.chdir && g_conf.chdir[0]) {
       if (::chdir(g_conf.chdir)) {
@@ -2742,7 +2656,7 @@ void SimpleMessenger::wait()
 
   dout(10) << "wait: done." << dendl;
   dout(1) << "shutdown complete." << dendl;
-  remove_pid_file();
+  pidfile_remove();
   started = false;
   did_bind = false;
   my_type = -1;