]> git.proxmox.com Git - ceph.git/blob - ceph/src/global/signal_handler.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / global / signal_handler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
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.
12 *
13 */
14
15 #include <sys/utsname.h>
16
17 #include "include/compat.h"
18 #include "pthread.h"
19
20 #include "common/ceph_mutex.h"
21 #include "common/BackTrace.h"
22 #include "common/debug.h"
23 #include "common/safe_io.h"
24 #include "common/version.h"
25
26 #include "include/uuid.h"
27 #include "global/pidfile.h"
28 #include "global/signal_handler.h"
29
30 #include <poll.h>
31 #include <signal.h>
32 #include <sstream>
33 #include <stdlib.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include "common/errno.h"
37 #if defined(_AIX)
38 extern char *sys_siglist[];
39 #endif
40
41 #define dout_context g_ceph_context
42
43 using std::ostringstream;
44 using std::string;
45
46 using ceph::BackTrace;
47 using ceph::JSONFormatter;
48
49 void install_sighandler(int signum, signal_handler_t handler, int flags)
50 {
51 int ret;
52 struct sigaction oldact;
53 struct sigaction act;
54 memset(&act, 0, sizeof(act));
55
56 act.sa_handler = handler;
57 sigemptyset(&act.sa_mask);
58 act.sa_flags = flags;
59
60 ret = sigaction(signum, &act, &oldact);
61 if (ret != 0) {
62 char buf[1024];
63 #if defined(__sun)
64 char message[SIG2STR_MAX];
65 sig2str(signum,message);
66 snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
67 "%d when trying to install a signal handler for %s\n",
68 ret, message);
69 #else
70 snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
71 "%d when trying to install a signal handler for %s\n",
72 ret, sig_str(signum));
73 #endif
74 dout_emergency(buf);
75 exit(1);
76 }
77 }
78
79 void sighup_handler(int signum)
80 {
81 g_ceph_context->reopen_logs();
82 }
83
84 static void reraise_fatal(int signum)
85 {
86 // Use default handler to dump core
87 signal(signum, SIG_DFL);
88 int ret = raise(signum);
89
90 // Normally, we won't get here. If we do, something is very weird.
91 char buf[1024];
92 if (ret) {
93 snprintf(buf, sizeof(buf), "reraise_fatal: failed to re-raise "
94 "signal %d\n", signum);
95 dout_emergency(buf);
96 }
97 else {
98 snprintf(buf, sizeof(buf), "reraise_fatal: default handler for "
99 "signal %d didn't terminate the process?\n", signum);
100 dout_emergency(buf);
101 }
102 exit(1);
103 }
104
105
106 // /etc/os-release looks like
107 //
108 // NAME=Fedora
109 // VERSION="28 (Server Edition)"
110 // ID=fedora
111 // VERSION_ID=28
112 //
113 // or
114 //
115 // NAME="Ubuntu"
116 // VERSION="16.04.3 LTS (Xenial Xerus)"
117 // ID=ubuntu
118 // ID_LIKE=debian
119 //
120 // get_from_os_release("FOO=bar\nTHIS=\"that\"\n", "FOO=", ...) will
121 // write "bar\0" to out buffer, which is assumed to be as large as the input
122 // file.
123 static int parse_from_os_release(
124 const char *file, const char *key,
125 char *out)
126 {
127 const char *p = strstr(file, key);
128 if (!p) {
129 return -1;
130 }
131 const char *start = p + strlen(key);
132 const char *end = strchr(start, '\n');
133 if (!end) {
134 return -1;
135 }
136 if (*start == '"' && *(end - 1) == '"') {
137 ++start;
138 --end;
139 }
140 if (start >= end) {
141 return -1;
142 }
143 memcpy(out, start, end - start);
144 out[end - start] = 0;
145 return 0;
146 }
147
148
149 void generate_crash_dump(char *base,
150 const BackTrace& bt,
151 std::map<std::string,std::string> *extra)
152 {
153 if (g_ceph_context &&
154 g_ceph_context->_conf->crash_dir.size()) {
155
156 // -- crash dump --
157 // id
158 ostringstream idss;
159 utime_t now = ceph_clock_now();
160 now.gmtime(idss);
161 uuid_d uuid;
162 uuid.generate_random();
163 idss << "_" << uuid;
164 string id = idss.str();
165 std::replace(id.begin(), id.end(), ' ', '_');
166
167 snprintf(base, PATH_MAX, "%s/%s",
168 g_ceph_context->_conf->crash_dir.c_str(),
169 id.c_str());
170 int r = ::mkdir(base, 0700);
171 if (r >= 0) {
172 char fn[PATH_MAX*2];
173 snprintf(fn, sizeof(fn)-1, "%s/meta", base);
174 int fd = ::open(fn, O_CREAT|O_WRONLY|O_CLOEXEC, 0600);
175 if (fd >= 0) {
176 JSONFormatter jf(true);
177 jf.open_object_section("crash");
178 jf.dump_string("crash_id", id);
179 now.gmtime(jf.dump_stream("timestamp"));
180 jf.dump_string("process_name", g_process_name);
181 jf.dump_string("entity_name", g_ceph_context->_conf->name.to_str());
182 jf.dump_string("ceph_version", ceph_version_to_str());
183
184 struct utsname u;
185 r = uname(&u);
186 if (r >= 0) {
187 jf.dump_string("utsname_hostname", u.nodename);
188 jf.dump_string("utsname_sysname", u.sysname);
189 jf.dump_string("utsname_release", u.release);
190 jf.dump_string("utsname_version", u.version);
191 jf.dump_string("utsname_machine", u.machine);
192 }
193 #if defined(__linux__)
194 // os-release
195 int in = ::open("/etc/os-release", O_RDONLY|O_CLOEXEC);
196 if (in >= 0) {
197 char buf[4096];
198 r = safe_read(in, buf, sizeof(buf)-1);
199 if (r >= 0) {
200 buf[r] = 0;
201 char v[4096];
202 if (parse_from_os_release(buf, "NAME=", v) >= 0) {
203 jf.dump_string("os_name", v);
204 }
205 if (parse_from_os_release(buf, "ID=", v) >= 0) {
206 jf.dump_string("os_id", v);
207 }
208 if (parse_from_os_release(buf, "VERSION_ID=", v) >= 0) {
209 jf.dump_string("os_version_id", v);
210 }
211 if (parse_from_os_release(buf, "VERSION=", v) >= 0) {
212 jf.dump_string("os_version", v);
213 }
214 }
215 ::close(in);
216 }
217 #endif
218
219 // assert?
220 if (g_assert_condition) {
221 jf.dump_string("assert_condition", g_assert_condition);
222 }
223 if (g_assert_func) {
224 jf.dump_string("assert_func", g_assert_func);
225 }
226 if (g_assert_file) {
227 jf.dump_string("assert_file", g_assert_file);
228 }
229 if (g_assert_line) {
230 jf.dump_unsigned("assert_line", g_assert_line);
231 }
232 if (g_assert_thread_name[0]) {
233 jf.dump_string("assert_thread_name", g_assert_thread_name);
234 }
235 if (g_assert_msg[0]) {
236 jf.dump_string("assert_msg", g_assert_msg);
237 }
238
239 // eio?
240 if (g_eio) {
241 jf.dump_bool("io_error", true);
242 if (g_eio_devname[0]) {
243 jf.dump_string("io_error_devname", g_eio_devname);
244 }
245 if (g_eio_path[0]) {
246 jf.dump_string("io_error_path", g_eio_path);
247 }
248 if (g_eio_error) {
249 jf.dump_int("io_error_code", g_eio_error);
250 }
251 if (g_eio_iotype) {
252 jf.dump_int("io_error_optype", g_eio_iotype);
253 }
254 if (g_eio_offset) {
255 jf.dump_unsigned("io_error_offset", g_eio_offset);
256 }
257 if (g_eio_length) {
258 jf.dump_unsigned("io_error_length", g_eio_length);
259 }
260 }
261
262 bt.dump(&jf);
263
264 if (extra) {
265 for (auto& i : *extra) {
266 jf.dump_string(i.first, i.second);
267 }
268 }
269
270 jf.close_section();
271 ostringstream oss;
272 jf.flush(oss);
273 string s = oss.str();
274 r = safe_write(fd, s.c_str(), s.size());
275 (void)r;
276 ::close(fd);
277 }
278 snprintf(fn, sizeof(fn)-1, "%s/done", base);
279 ::creat(fn, 0444);
280 }
281 }
282 }
283
284 static void handle_oneshot_fatal_signal(int signum)
285 {
286 constexpr static pid_t NULL_TID{0};
287 static std::atomic<pid_t> handler_tid{NULL_TID};
288 if (auto expected{NULL_TID};
289 !handler_tid.compare_exchange_strong(expected, ceph_gettid())) {
290 if (expected == ceph_gettid()) {
291 // The handler code may itself trigger a SIGSEGV if the heap is corrupt.
292 // In that case, SIG_DFL followed by return specifies that the default
293 // signal handler -- presumably dump core -- will handle it.
294 signal(signum, SIG_DFL);
295 } else {
296 // Huh, another thread got into troubles while we are handling the fault.
297 // If this is i.e. SIGSEGV handler, returning means retrying the faulty
298 // instruction one more time, and thus all those extra threads will run
299 // into a busy-wait basically.
300 }
301 return;
302 }
303
304 char buf[1024];
305 char pthread_name[16] = {0}; //limited by 16B include terminating null byte.
306 int r = ceph_pthread_getname(pthread_self(), pthread_name, sizeof(pthread_name));
307 (void)r;
308 #if defined(__sun)
309 char message[SIG2STR_MAX];
310 sig2str(signum,message);
311 snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
312 "in thread %llx thread_name:%s\n", message, (unsigned long long)pthread_self(),
313 pthread_name);
314 #else
315 snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
316 "in thread %llx thread_name:%s\n", sig_str(signum), (unsigned long long)pthread_self(),
317 pthread_name);
318 #endif
319 dout_emergency(buf);
320 pidfile_remove();
321
322 // TODO: don't use an ostringstream here. It could call malloc(), which we
323 // don't want inside a signal handler.
324 // Also fix the backtrace code not to allocate memory.
325 ClibBackTrace bt(1);
326 ostringstream oss;
327 bt.print(oss);
328 dout_emergency(oss.str());
329
330 char crash_base[PATH_MAX] = { 0 };
331
332 generate_crash_dump(crash_base, bt);
333
334 // avoid recursion back into logging code if that is where
335 // we got the SEGV.
336 if (g_ceph_context &&
337 g_ceph_context->_log &&
338 !g_ceph_context->_log->is_inside_log_lock()) {
339 // dump to log. this uses the heap extensively, but we're better
340 // off trying than not.
341 derr << buf << std::endl;
342 bt.print(*_dout);
343 *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
344 << "is needed to interpret this.\n"
345 << dendl;
346
347 g_ceph_context->_log->dump_recent();
348
349 if (crash_base[0]) {
350 char fn[PATH_MAX*2];
351 snprintf(fn, sizeof(fn)-1, "%s/log", crash_base);
352 g_ceph_context->_log->set_log_file(fn);
353 g_ceph_context->_log->reopen_log_file();
354 g_ceph_context->_log->dump_recent();
355 }
356 }
357
358 if (g_eio) {
359 // if this was an EIO crash, we don't need to trigger a core dump,
360 // since the problem is hardware, or some layer beneath us.
361 _exit(EIO);
362 } else {
363 reraise_fatal(signum);
364 }
365 }
366
367 void install_standard_sighandlers(void)
368 {
369 install_sighandler(SIGSEGV, handle_oneshot_fatal_signal, SA_NODEFER);
370 install_sighandler(SIGABRT, handle_oneshot_fatal_signal, SA_NODEFER);
371 install_sighandler(SIGBUS, handle_oneshot_fatal_signal, SA_NODEFER);
372 install_sighandler(SIGILL, handle_oneshot_fatal_signal, SA_NODEFER);
373 install_sighandler(SIGFPE, handle_oneshot_fatal_signal, SA_NODEFER);
374 install_sighandler(SIGXCPU, handle_oneshot_fatal_signal, SA_NODEFER);
375 install_sighandler(SIGXFSZ, handle_oneshot_fatal_signal, SA_NODEFER);
376 install_sighandler(SIGSYS, handle_oneshot_fatal_signal, SA_NODEFER);
377 }
378
379
380
381 /// --- safe handler ---
382
383 #include "common/Thread.h"
384 #include <errno.h>
385
386 #ifdef __APPLE__
387 #include <libproc.h>
388
389 string get_name_by_pid(pid_t pid)
390 {
391 char buf[PROC_PIDPATHINFO_MAXSIZE];
392 int ret = proc_pidpath(pid, buf, sizeof(buf));
393 if (ret == 0) {
394 derr << "Fail to proc_pidpath(" << pid << ")"
395 << " error = " << cpp_strerror(ret)
396 << dendl;
397 return "<unknown>";
398 }
399 return string(buf, ret);
400 }
401 #else
402 string get_name_by_pid(pid_t pid)
403 {
404 // If the PID is 0, its means the sender is the Kernel itself
405 if (pid == 0) {
406 return "Kernel";
407 }
408 char proc_pid_path[PATH_MAX] = {0};
409 snprintf(proc_pid_path, PATH_MAX, PROCPREFIX "/proc/%d/cmdline", pid);
410 int fd = open(proc_pid_path, O_RDONLY);
411
412 if (fd < 0) {
413 fd = -errno;
414 derr << "Fail to open '" << proc_pid_path
415 << "' error = " << cpp_strerror(fd)
416 << dendl;
417 return "<unknown>";
418 }
419 // assuming the cmdline length does not exceed PATH_MAX. if it
420 // really does, it's fine to return a truncated version.
421 char buf[PATH_MAX] = {0};
422 int ret = read(fd, buf, sizeof(buf));
423 close(fd);
424 if (ret < 0) {
425 ret = -errno;
426 derr << "Fail to read '" << proc_pid_path
427 << "' error = " << cpp_strerror(ret)
428 << dendl;
429 return "<unknown>";
430 }
431 std::replace(buf, buf + ret, '\0', ' ');
432 return string(buf, ret);
433 }
434 #endif
435
436 /**
437 * safe async signal handler / dispatcher
438 *
439 * This is an async unix signal handler based on the design from
440 *
441 * http://evbergen.home.xs4all.nl/unix-signals.html
442 *
443 * Features:
444 * - no unsafe work is done in the signal handler itself
445 * - callbacks are called from a regular thread
446 * - signals are not lost, unless multiple instances of the same signal
447 * are sent twice in quick succession.
448 */
449 struct SignalHandler : public Thread {
450 /// to kick the thread, for shutdown, new handlers, etc.
451 int pipefd[2]; // write to [1], read from [0]
452
453 /// to signal shutdown
454 bool stop = false;
455
456 /// for an individual signal
457 struct safe_handler {
458
459 safe_handler() {
460 memset(pipefd, 0, sizeof(pipefd));
461 memset(&handler, 0, sizeof(handler));
462 memset(&info_t, 0, sizeof(info_t));
463 }
464
465 siginfo_t info_t;
466 int pipefd[2]; // write to [1], read from [0]
467 signal_handler_t handler;
468 };
469
470 /// all handlers
471 safe_handler *handlers[32] = {nullptr};
472
473 /// to protect the handlers array
474 ceph::mutex lock = ceph::make_mutex("SignalHandler::lock");
475
476 SignalHandler() {
477 // create signal pipe
478 int r = pipe_cloexec(pipefd, 0);
479 ceph_assert(r == 0);
480 r = fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
481 ceph_assert(r == 0);
482
483 // create thread
484 create("signal_handler");
485 }
486
487 ~SignalHandler() override {
488 shutdown();
489 }
490
491 void signal_thread() {
492 int r = write(pipefd[1], "\0", 1);
493 ceph_assert(r == 1);
494 }
495
496 void shutdown() {
497 stop = true;
498 signal_thread();
499 join();
500 }
501
502 // thread entry point
503 void *entry() override {
504 while (!stop) {
505 // build fd list
506 struct pollfd fds[33];
507
508 lock.lock();
509 int num_fds = 0;
510 fds[num_fds].fd = pipefd[0];
511 fds[num_fds].events = POLLIN | POLLERR;
512 fds[num_fds].revents = 0;
513 ++num_fds;
514 for (unsigned i=0; i<32; i++) {
515 if (handlers[i]) {
516 fds[num_fds].fd = handlers[i]->pipefd[0];
517 fds[num_fds].events = POLLIN | POLLERR;
518 fds[num_fds].revents = 0;
519 ++num_fds;
520 }
521 }
522 lock.unlock();
523
524 // wait for data on any of those pipes
525 int r = poll(fds, num_fds, -1);
526 if (stop)
527 break;
528 if (r > 0) {
529 char v;
530
531 // consume byte from signal socket, if any.
532 TEMP_FAILURE_RETRY(read(pipefd[0], &v, 1));
533
534 lock.lock();
535 for (unsigned signum=0; signum<32; signum++) {
536 if (handlers[signum]) {
537 r = read(handlers[signum]->pipefd[0], &v, 1);
538 if (r == 1) {
539 siginfo_t * siginfo = &handlers[signum]->info_t;
540 ostringstream message;
541 message << "received signal: " << sig_str(signum);
542 switch (siginfo->si_code) {
543 case SI_USER:
544 message << " from " << get_name_by_pid(siginfo->si_pid);
545 // If PID is undefined, it doesn't have a meaning to be displayed
546 if (siginfo->si_pid) {
547 message << " (PID: " << siginfo->si_pid << ")";
548 } else {
549 message << " ( Could be generated by pthread_kill(), raise(), abort(), alarm() )";
550 }
551 message << " UID: " << siginfo->si_uid;
552 break;
553 default:
554 /* As we have a not expected signal, let's report the structure to help debugging */
555 message << ", si_code : " << siginfo->si_code;
556 message << ", si_value (int): " << siginfo->si_value.sival_int;
557 message << ", si_value (ptr): " << siginfo->si_value.sival_ptr;
558 message << ", si_errno: " << siginfo->si_errno;
559 message << ", si_pid : " << siginfo->si_pid;
560 message << ", si_uid : " << siginfo->si_uid;
561 message << ", si_addr" << siginfo->si_addr;
562 message << ", si_status" << siginfo->si_status;
563 break;
564 }
565 derr << message.str() << dendl;
566 handlers[signum]->handler(signum);
567 }
568 }
569 }
570 lock.unlock();
571 }
572 }
573 return NULL;
574 }
575
576 void queue_signal(int signum) {
577 // If this signal handler is registered, the callback must be
578 // defined. We can do this without the lock because we will never
579 // have the signal handler defined without the handlers entry also
580 // being filled in.
581 ceph_assert(handlers[signum]);
582 int r = write(handlers[signum]->pipefd[1], " ", 1);
583 ceph_assert(r == 1);
584 }
585
586 void queue_signal_info(int signum, siginfo_t *siginfo, void * content) {
587 // If this signal handler is registered, the callback must be
588 // defined. We can do this without the lock because we will never
589 // have the signal handler defined without the handlers entry also
590 // being filled in.
591 ceph_assert(handlers[signum]);
592 memcpy(&handlers[signum]->info_t, siginfo, sizeof(siginfo_t));
593 int r = write(handlers[signum]->pipefd[1], " ", 1);
594 ceph_assert(r == 1);
595 }
596
597 void register_handler(int signum, signal_handler_t handler, bool oneshot);
598 void unregister_handler(int signum, signal_handler_t handler);
599 };
600
601 static SignalHandler *g_signal_handler = NULL;
602
603 static void handler_signal_hook(int signum, siginfo_t * siginfo, void * content) {
604 g_signal_handler->queue_signal_info(signum, siginfo, content);
605 }
606
607 void SignalHandler::register_handler(int signum, signal_handler_t handler, bool oneshot)
608 {
609 int r;
610
611 ceph_assert(signum >= 0 && signum < 32);
612
613 safe_handler *h = new safe_handler;
614
615 r = pipe_cloexec(h->pipefd, 0);
616 ceph_assert(r == 0);
617 r = fcntl(h->pipefd[0], F_SETFL, O_NONBLOCK);
618 ceph_assert(r == 0);
619
620 h->handler = handler;
621 lock.lock();
622 handlers[signum] = h;
623 lock.unlock();
624
625 // signal thread so that it sees our new handler
626 signal_thread();
627
628 // install our handler
629 struct sigaction oldact;
630 struct sigaction act;
631 memset(&act, 0, sizeof(act));
632
633 act.sa_handler = (signal_handler_t)handler_signal_hook;
634 sigfillset(&act.sa_mask); // mask all signals in the handler
635 act.sa_flags = SA_SIGINFO | (oneshot ? SA_RESETHAND : 0);
636 int ret = sigaction(signum, &act, &oldact);
637 ceph_assert(ret == 0);
638 }
639
640 void SignalHandler::unregister_handler(int signum, signal_handler_t handler)
641 {
642 ceph_assert(signum >= 0 && signum < 32);
643 safe_handler *h = handlers[signum];
644 ceph_assert(h);
645 ceph_assert(h->handler == handler);
646
647 // restore to default
648 signal(signum, SIG_DFL);
649
650 // _then_ remove our handlers entry
651 lock.lock();
652 handlers[signum] = NULL;
653 lock.unlock();
654
655 // this will wake up select() so that worker thread sees our handler is gone
656 close(h->pipefd[0]);
657 close(h->pipefd[1]);
658 delete h;
659 }
660
661
662 // -------
663
664 void init_async_signal_handler()
665 {
666 ceph_assert(!g_signal_handler);
667 g_signal_handler = new SignalHandler;
668 }
669
670 void shutdown_async_signal_handler()
671 {
672 ceph_assert(g_signal_handler);
673 delete g_signal_handler;
674 g_signal_handler = NULL;
675 }
676
677 void queue_async_signal(int signum)
678 {
679 ceph_assert(g_signal_handler);
680 g_signal_handler->queue_signal(signum);
681 }
682
683 void register_async_signal_handler(int signum, signal_handler_t handler)
684 {
685 ceph_assert(g_signal_handler);
686 g_signal_handler->register_handler(signum, handler, false);
687 }
688
689 void register_async_signal_handler_oneshot(int signum, signal_handler_t handler)
690 {
691 ceph_assert(g_signal_handler);
692 g_signal_handler->register_handler(signum, handler, true);
693 }
694
695 void unregister_async_signal_handler(int signum, signal_handler_t handler)
696 {
697 ceph_assert(g_signal_handler);
698 g_signal_handler->unregister_handler(signum, handler);
699 }
700
701
702