]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common: move signal blocking into signal.cc
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Fri, 21 Jan 2011 14:27:55 +0000 (06:27 -0800)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Fri, 21 Jan 2011 14:53:04 +0000 (06:53 -0800)
Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/common/Thread.h
src/common/signal.cc
src/common/signal.h

index a567d2dbac4c33c9065ff67df79b6c3f3c335ff9..2a2c16580a92ad4920a0e1043d81696aee296067 100644 (file)
 #ifndef CEPH_THREAD_H
 #define CEPH_THREAD_H
 
+#include "common/signal.h"
+#include "include/atomic.h"
+
+#include <errno.h>
 #include <pthread.h>
 #include <signal.h>
-#include <errno.h>
-#include "include/atomic.h"
 
 extern atomic_t _num_threads;  // hack: in config.cc
 
@@ -55,10 +57,6 @@ class Thread {
       return -EINVAL;
   }
   int create(size_t stacksize = 0) {
-    // mask signals in child's thread
-    sigset_t newmask, oldmask;
-    sigfillset(&newmask);
-    pthread_sigmask(SIG_BLOCK, &newmask, &oldmask);
 
     pthread_attr_t *thread_attr = NULL;
     stacksize &= PAGE_MASK;  // must be multiple of page
@@ -67,11 +65,18 @@ class Thread {
       pthread_attr_init(thread_attr);
       pthread_attr_setstacksize(thread_attr, stacksize);
     }
+
+    // The child thread will inherit our signal mask.  We want it to block all
+    // signals, so set our mask to that.  (It's ok to block signals for a
+    // little while-- they will just be delivered to another thread or
+    // delieverd to this thread later.)
+    sigset_t old_sigset;
+    block_all_signals(&old_sigset);
     int r = pthread_create(&thread_id, thread_attr, _entry_func, (void*)this);
+    restore_sigset(&old_sigset);
 
     if (thread_attr) 
       free(thread_attr);
-    pthread_sigmask(SIG_SETMASK, &oldmask, 0);
 
     if (r) {
       char buf[80];
index 1548f48565a77321c4553e711dde8c11541324bc..5a55fd3cd6324e812809396252318c5a9e83fd85 100644 (file)
@@ -15,6 +15,7 @@
 #include "common/BackTrace.h"
 #include "common/Logger.h"
 #include "common/debug.h"
+#include "config.h"
 
 #include <signal.h>
 #include <sstream>
@@ -22,6 +23,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#define dout_prefix *_dout
+#define derr dout(0)
+
 typedef void (*signal_handler_t)(int);
 
 static void install_sighandler(int signum, signal_handler_t handler, int flags)
@@ -113,3 +117,44 @@ void install_standard_sighandlers(void)
   install_sighandler(SIGXFSZ, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
   install_sighandler(SIGSYS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
 }
+
+void block_all_signals(sigset_t *old_sigset)
+{
+  sigset_t sigset;
+  sigfillset(&sigset);
+  sigdelset(&sigset, SIGKILL);
+  if (pthread_sigmask(SIG_BLOCK, &sigset, old_sigset)) {
+    derr << "block_all_signals: sigprocmask failed" << dendl;
+    if (old_sigset)
+      sigaddset(old_sigset, SIGKILL);
+    return;
+  }
+  if (old_sigset)
+    sigdelset(old_sigset, SIGKILL);
+}
+
+void restore_sigset(const sigset_t *old_sigset)
+{
+  if (sigismember(old_sigset, SIGKILL) != 0) {
+    derr << "restore_sigset: not restoring invalid old_sigset" << dendl;
+    return;
+  }
+  if (pthread_sigmask(SIG_SETMASK, old_sigset, NULL)) {
+    derr << "restore_sigset: sigprocmask failed" << dendl;
+  }
+}
+
+void unblock_all_signals(sigset_t *old_sigset)
+{
+  sigset_t sigset;
+  sigfillset(&sigset);
+  sigdelset(&sigset, SIGKILL);
+  if (pthread_sigmask(SIG_UNBLOCK, &sigset, old_sigset)) {
+    derr << "unblock_all_signals: sigprocmask failed" << dendl;
+    if (old_sigset)
+      sigaddset(old_sigset, SIGKILL);
+    return;
+  }
+  if (old_sigset)
+    sigdelset(old_sigset, SIGKILL);
+}
index 6364cc406750d3f9c8e83a25d5d5de208212ddf2..0ffa700c92a6b4250975420365af677da8df933f 100644 (file)
 #ifndef CEPH_COMMON_SIGNAL_H
 #define CEPH_COMMON_SIGNAL_H
 
+// Install the standard Ceph signal handlers
 void install_standard_sighandlers(void);
 
+// Returns a string showing the set of blocked signals for the calling thread.
+// Other threads may have a different set (this is per-thread thing).
 std::string signal_mask_to_str();
 
+// Block all signals. On success, stores the old set of blocked signals in
+// old_sigset. On failure, stores an invalid set of blocked signals in
+// old_sigset.
+void block_all_signals(sigset_t *old_sigset);
+
+// Restore the set of blocked signals. Will not restore an invalid set of
+// blocked signals.
+void restore_sigset(const sigset_t *old_sigset);
+
+// Unblock all signals. On success, stores the old set of blocked signals in
+// old_sigset. On failure, stores an invalid set of blocked signals in
+// old_sigset.
+void unblock_all_signals(sigset_t *old_sigset);
+
 #endif