From: Colin Patrick McCabe Date: Thu, 3 Mar 2011 15:08:09 +0000 (-0800) Subject: common: block SIGPIPE everywhere we can X-Git-Tag: v0.25~29 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b941cfdc87e5d3fa768fb3b2d1246427d1c4b89b;p=ceph.git common: block SIGPIPE everywhere we can It's much better to get EPIPE than SIGPIPE. Block SIGPIPE in all threads we create. In the daemon, block SIGPIPE in the main thread. Signed-off-by: Colin McCabe --- diff --git a/src/common/Thread.h b/src/common/Thread.h index a3f45e2500fb..5ab4bfd3c5f1 100644 --- a/src/common/Thread.h +++ b/src/common/Thread.h @@ -66,19 +66,21 @@ class Thread { } int r; + + // The child thread will inherit our signal mask. Set our signal mask to + // the set of signals we want to block. (It's ok to block signals more + // signals than usual for a little while-- they will just be delivered to + // another thread or delieverd to this thread later.) + sigset_t old_sigset; if (g_code_env == CODE_ENVIRONMENT_LIBRARY) { - // 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); - r = pthread_create(&thread_id, thread_attr, _entry_func, (void*)this); - restore_sigset(&old_sigset); + block_signals(&old_sigset, NULL); } else { - r = pthread_create(&thread_id, thread_attr, _entry_func, (void*)this); + int to_block[] = { SIGPIPE , 0 }; + block_signals(&old_sigset, to_block); } + r = pthread_create(&thread_id, thread_attr, _entry_func, (void*)this); + restore_sigset(&old_sigset); if (thread_attr) free(thread_attr); diff --git a/src/common/common_init.cc b/src/common/common_init.cc index 09c948978ef2..fd29d4ec0c3a 100644 --- a/src/common/common_init.cc +++ b/src/common/common_init.cc @@ -134,6 +134,10 @@ void common_init(std::vector& args, const char *module_type, int fl g_conf.log_to_stderr = LOG_TO_STDERR_SOME; set_cv(&g_conf.log_dir, "/var/log/ceph"); set_cv(&g_conf.pid_file, "/var/run/ceph/$type.$id.pid"); + + // block SIGPIPE + int siglist[] = { SIGPIPE, 0 }; + block_signals(NULL, siglist); } else { g_conf.pid_file = 0; diff --git a/src/common/signal.cc b/src/common/signal.cc index e569cff19e78..64886e149b63 100644 --- a/src/common/signal.cc +++ b/src/common/signal.cc @@ -124,10 +124,20 @@ void install_standard_sighandlers(void) install_sighandler(SIGSYS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER); } -void block_all_signals(sigset_t *old_sigset) +void block_signals(sigset_t *old_sigset, int *siglist) { sigset_t sigset; - sigfillset(&sigset); + if (!siglist) { + sigfillset(&sigset); + } + else { + int i = 0; + sigemptyset(&sigset); + while (siglist[i]) { + sigaddset(&sigset, siglist[i]); + ++i; + } + } sigdelset(&sigset, SIGKILL); if (pthread_sigmask(SIG_BLOCK, &sigset, old_sigset)) { derr << "block_all_signals: sigprocmask failed" << dendl; diff --git a/src/common/signal.h b/src/common/signal.h index 1081e337cab1..ed9ef2891dcf 100644 --- a/src/common/signal.h +++ b/src/common/signal.h @@ -32,10 +32,13 @@ void install_standard_sighandlers(void); // 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 +// Block a list of signals. If siglist == NULL, blocks all signals. +// If not, the list is terminated with a 0 element. +// +// 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); +void block_signals(sigset_t *old_sigset, int *siglist); // Restore the set of blocked signals. Will not restore an invalid set of // blocked signals.