#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
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
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];
#include "common/BackTrace.h"
#include "common/Logger.h"
#include "common/debug.h"
+#include "config.h"
#include <signal.h>
#include <sstream>
#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)
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);
+}
#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