1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "include/compat.h"
18 #include "common/BackTrace.h"
19 #include "common/debug.h"
20 #include "global/pidfile.h"
21 #include "global/signal_handler.h"
28 #include <sys/types.h>
29 #include "common/errno.h"
31 extern char *sys_siglist[];
34 #define dout_context g_ceph_context
36 void install_sighandler(int signum, signal_handler_t handler, int flags)
39 struct sigaction oldact;
41 memset(&act, 0, sizeof(act));
43 act.sa_handler = handler;
44 sigemptyset(&act.sa_mask);
47 ret = sigaction(signum, &act, &oldact);
51 char message[SIG2STR_MAX];
52 sig2str(signum,message);
53 snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
54 "%d when trying to install a signal handler for %s\n",
57 snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
58 "%d when trying to install a signal handler for %s\n",
59 ret, sig_str(signum));
66 void sighup_handler(int signum)
68 g_ceph_context->reopen_logs();
71 static void reraise_fatal(int signum)
73 // Use default handler to dump core
74 int ret = raise(signum);
76 // Normally, we won't get here. If we do, something is very weird.
79 snprintf(buf, sizeof(buf), "reraise_fatal: failed to re-raise "
80 "signal %d\n", signum);
84 snprintf(buf, sizeof(buf), "reraise_fatal: default handler for "
85 "signal %d didn't terminate the process?\n", signum);
91 static void handle_fatal_signal(int signum)
93 // This code may itself trigger a SIGSEGV if the heap is corrupt. In that
94 // case, SA_RESETHAND specifies that the default signal handler--
95 // presumably dump core-- will handle it.
97 char pthread_name[16] = {0}; //limited by 16B include terminating null byte.
98 int r = ceph_pthread_getname(pthread_self(), pthread_name, sizeof(pthread_name));
101 char message[SIG2STR_MAX];
102 sig2str(signum,message);
103 snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
104 "in thread %llx thread_name:%s\n", message, (unsigned long long)pthread_self(),
107 snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
108 "in thread %llx thread_name:%s\n", sig_str(signum), (unsigned long long)pthread_self(),
114 // TODO: don't use an ostringstream here. It could call malloc(), which we
115 // don't want inside a signal handler.
116 // Also fix the backtrace code not to allocate memory.
120 dout_emergency(oss.str());
122 // avoid recursion back into logging code if that is where
124 if (g_ceph_context &&
125 g_ceph_context->_log &&
126 !g_ceph_context->_log->is_inside_log_lock()) {
127 // dump to log. this uses the heap extensively, but we're better
128 // off trying than not.
129 derr << buf << std::endl;
131 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
132 << "is needed to interpret this.\n"
135 g_ceph_context->_log->dump_recent();
138 reraise_fatal(signum);
141 void install_standard_sighandlers(void)
143 install_sighandler(SIGSEGV, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
144 install_sighandler(SIGABRT, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
145 install_sighandler(SIGBUS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
146 install_sighandler(SIGILL, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
147 install_sighandler(SIGFPE, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
148 install_sighandler(SIGXCPU, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
149 install_sighandler(SIGXFSZ, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
150 install_sighandler(SIGSYS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
155 /// --- safe handler ---
157 #include "common/Thread.h"
160 string get_name_by_pid(pid_t pid)
162 char proc_pid_path[PATH_MAX] = {0};
163 snprintf(proc_pid_path, PATH_MAX, PROCPREFIX "/proc/%d/cmdline", pid);
164 int fd = open(proc_pid_path, O_RDONLY);
168 derr << "Fail to open '" << proc_pid_path
169 << "' error = " << cpp_strerror(fd)
173 // assuming the cmdline length does not exceed PATH_MAX. if it
174 // really does, it's fine to return a truncated version.
175 char buf[PATH_MAX] = {0};
176 int ret = read(fd, buf, sizeof(buf));
180 derr << "Fail to read '" << proc_pid_path
181 << "' error = " << cpp_strerror(ret)
185 std::replace(buf, buf + ret, '\0', ' ');
186 return string(buf, ret);
191 * safe async signal handler / dispatcher
193 * This is an async unix signal handler based on the design from
195 * http://evbergen.home.xs4all.nl/unix-signals.html
198 * - no unsafe work is done in the signal handler itself
199 * - callbacks are called from a regular thread
200 * - signals are not lost, unless multiple instances of the same signal
201 * are sent twice in quick succession.
203 struct SignalHandler : public Thread {
204 /// to kick the thread, for shutdown, new handlers, etc.
205 int pipefd[2]; // write to [1], read from [0]
207 /// to signal shutdown
210 /// for an individual signal
211 struct safe_handler {
214 memset(pipefd, 0, sizeof(pipefd));
215 memset(&handler, 0, sizeof(handler));
216 memset(&info_t, 0, sizeof(info_t));
220 int pipefd[2]; // write to [1], read from [0]
221 signal_handler_t handler;
225 safe_handler *handlers[32] = {nullptr};
227 /// to protect the handlers array
231 : stop(false), lock("SignalHandler::lock")
233 // create signal pipe
234 int r = pipe(pipefd);
236 r = fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
240 create("signal_handler");
243 ~SignalHandler() override {
247 void signal_thread() {
248 int r = write(pipefd[1], "\0", 1);
258 // thread entry point
259 void *entry() override {
262 struct pollfd fds[33];
266 fds[num_fds].fd = pipefd[0];
267 fds[num_fds].events = POLLIN | POLLERR;
268 fds[num_fds].revents = 0;
270 for (unsigned i=0; i<32; i++) {
272 fds[num_fds].fd = handlers[i]->pipefd[0];
273 fds[num_fds].events = POLLIN | POLLERR;
274 fds[num_fds].revents = 0;
280 // wait for data on any of those pipes
281 int r = poll(fds, num_fds, -1);
287 // consume byte from signal socket, if any.
288 TEMP_FAILURE_RETRY(read(pipefd[0], &v, 1));
291 for (unsigned signum=0; signum<32; signum++) {
292 if (handlers[signum]) {
293 r = read(handlers[signum]->pipefd[0], &v, 1);
295 siginfo_t * siginfo = &handlers[signum]->info_t;
296 string task_name = get_name_by_pid(siginfo->si_pid);
297 derr << "received signal: " << sig_str(signum)
298 << " from " << " PID: " << siginfo->si_pid
299 << " task name: " << task_name
300 << " UID: " << siginfo->si_uid
302 handlers[signum]->handler(signum);
312 void queue_signal(int signum) {
313 // If this signal handler is registered, the callback must be
314 // defined. We can do this without the lock because we will never
315 // have the signal handler defined without the handlers entry also
317 assert(handlers[signum]);
318 int r = write(handlers[signum]->pipefd[1], " ", 1);
322 void queue_signal_info(int signum, siginfo_t *siginfo, void * content) {
323 // If this signal handler is registered, the callback must be
324 // defined. We can do this without the lock because we will never
325 // have the signal handler defined without the handlers entry also
327 assert(handlers[signum]);
328 memcpy(&handlers[signum]->info_t, siginfo, sizeof(siginfo_t));
329 int r = write(handlers[signum]->pipefd[1], " ", 1);
333 void register_handler(int signum, signal_handler_t handler, bool oneshot);
334 void unregister_handler(int signum, signal_handler_t handler);
337 static SignalHandler *g_signal_handler = NULL;
339 static void handler_signal_hook(int signum, siginfo_t * siginfo, void * content) {
340 g_signal_handler->queue_signal_info(signum, siginfo, content);
343 void SignalHandler::register_handler(int signum, signal_handler_t handler, bool oneshot)
347 assert(signum >= 0 && signum < 32);
349 safe_handler *h = new safe_handler;
353 r = fcntl(h->pipefd[0], F_SETFL, O_NONBLOCK);
356 h->handler = handler;
358 handlers[signum] = h;
361 // signal thread so that it sees our new handler
364 // install our handler
365 struct sigaction oldact;
366 struct sigaction act;
367 memset(&act, 0, sizeof(act));
369 act.sa_handler = (signal_handler_t)handler_signal_hook;
370 sigfillset(&act.sa_mask); // mask all signals in the handler
371 act.sa_flags = SA_SIGINFO | (oneshot ? SA_RESETHAND : 0);
372 int ret = sigaction(signum, &act, &oldact);
376 void SignalHandler::unregister_handler(int signum, signal_handler_t handler)
378 assert(signum >= 0 && signum < 32);
379 safe_handler *h = handlers[signum];
381 assert(h->handler == handler);
383 // restore to default
384 signal(signum, SIG_DFL);
386 // _then_ remove our handlers entry
388 handlers[signum] = NULL;
391 // this will wake up select() so that worker thread sees our handler is gone
400 void init_async_signal_handler()
402 assert(!g_signal_handler);
403 g_signal_handler = new SignalHandler;
406 void shutdown_async_signal_handler()
408 assert(g_signal_handler);
409 delete g_signal_handler;
410 g_signal_handler = NULL;
413 void queue_async_signal(int signum)
415 assert(g_signal_handler);
416 g_signal_handler->queue_signal(signum);
419 void register_async_signal_handler(int signum, signal_handler_t handler)
421 assert(g_signal_handler);
422 g_signal_handler->register_handler(signum, handler, false);
425 void register_async_signal_handler_oneshot(int signum, signal_handler_t handler)
427 assert(g_signal_handler);
428 g_signal_handler->register_handler(signum, handler, true);
431 void unregister_async_signal_handler(int signum, signal_handler_t handler)
433 assert(g_signal_handler);
434 g_signal_handler->unregister_handler(signum, handler);