From: Colin Patrick McCabe Date: Fri, 21 Jan 2011 14:27:55 +0000 (-0800) Subject: common: move signal blocking into signal.cc X-Git-Tag: v0.25~262 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f2ce966b810a90659dc58af0e06d3d95d08b3adb;p=ceph.git common: move signal blocking into signal.cc Signed-off-by: Colin McCabe --- diff --git a/src/common/Thread.h b/src/common/Thread.h index e7da795dbddf..35984e7d88a8 100644 --- a/src/common/Thread.h +++ b/src/common/Thread.h @@ -16,10 +16,12 @@ #ifndef CEPH_THREAD_H #define CEPH_THREAD_H +#include "common/signal.h" +#include "include/atomic.h" + +#include #include #include -#include -#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]; diff --git a/src/common/signal.cc b/src/common/signal.cc index 1548f48565a7..708f60540297 100644 --- a/src/common/signal.cc +++ b/src/common/signal.cc @@ -15,6 +15,7 @@ #include "common/BackTrace.h" #include "common/Logger.h" #include "common/debug.h" +#include "config.h" #include #include @@ -22,6 +23,8 @@ #include #include +#define dout_prefix *_dout + typedef void (*signal_handler_t)(int); static void install_sighandler(int signum, signal_handler_t handler, int flags) @@ -113,3 +116,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); +} diff --git a/src/common/signal.h b/src/common/signal.h index 6364cc406750..0ffa700c92a6 100644 --- a/src/common/signal.h +++ b/src/common/signal.h @@ -15,8 +15,25 @@ #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