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 <sys/utsname.h>
17 #include "include/compat.h"
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"
26 #include "include/uuid.h"
27 #include "global/pidfile.h"
28 #include "global/signal_handler.h"
35 #include <sys/types.h>
36 #include "common/errno.h"
38 extern char *sys_siglist
[];
41 #define dout_context g_ceph_context
43 using std::ostringstream
;
46 using ceph::BackTrace
;
47 using ceph::JSONFormatter
;
49 void install_sighandler(int signum
, signal_handler_t handler
, int flags
)
52 struct sigaction oldact
;
54 memset(&act
, 0, sizeof(act
));
56 act
.sa_handler
= handler
;
57 sigemptyset(&act
.sa_mask
);
60 ret
= sigaction(signum
, &act
, &oldact
);
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",
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
));
79 void sighup_handler(int signum
)
81 g_ceph_context
->reopen_logs();
84 static void reraise_fatal(int signum
)
86 // Use default handler to dump core
87 signal(signum
, SIG_DFL
);
88 int ret
= raise(signum
);
90 // Normally, we won't get here. If we do, something is very weird.
93 snprintf(buf
, sizeof(buf
), "reraise_fatal: failed to re-raise "
94 "signal %d\n", signum
);
98 snprintf(buf
, sizeof(buf
), "reraise_fatal: default handler for "
99 "signal %d didn't terminate the process?\n", signum
);
106 // /etc/os-release looks like
109 // VERSION="28 (Server Edition)"
116 // VERSION="16.04.3 LTS (Xenial Xerus)"
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
123 static int parse_from_os_release(
124 const char *file
, const char *key
,
127 const char *p
= strstr(file
, key
);
131 const char *start
= p
+ strlen(key
);
132 const char *end
= strchr(start
, '\n');
136 if (*start
== '"' && *(end
- 1) == '"') {
143 memcpy(out
, start
, end
- start
);
144 out
[end
- start
] = 0;
149 void generate_crash_dump(char *base
,
151 std::map
<std::string
,std::string
> *extra
)
153 if (g_ceph_context
&&
154 g_ceph_context
->_conf
->crash_dir
.size()) {
159 utime_t now
= ceph_clock_now();
162 uuid
.generate_random();
164 string id
= idss
.str();
165 std::replace(id
.begin(), id
.end(), ' ', '_');
167 snprintf(base
, PATH_MAX
, "%s/%s",
168 g_ceph_context
->_conf
->crash_dir
.c_str(),
170 int r
= ::mkdir(base
, 0700);
173 snprintf(fn
, sizeof(fn
)-1, "%s/meta", base
);
174 int fd
= ::open(fn
, O_CREAT
|O_WRONLY
|O_CLOEXEC
, 0600);
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());
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
);
193 #if defined(__linux__)
195 int in
= ::open("/etc/os-release", O_RDONLY
|O_CLOEXEC
);
198 r
= safe_read(in
, buf
, sizeof(buf
)-1);
202 if (parse_from_os_release(buf
, "NAME=", v
) >= 0) {
203 jf
.dump_string("os_name", v
);
205 if (parse_from_os_release(buf
, "ID=", v
) >= 0) {
206 jf
.dump_string("os_id", v
);
208 if (parse_from_os_release(buf
, "VERSION_ID=", v
) >= 0) {
209 jf
.dump_string("os_version_id", v
);
211 if (parse_from_os_release(buf
, "VERSION=", v
) >= 0) {
212 jf
.dump_string("os_version", v
);
220 if (g_assert_condition
) {
221 jf
.dump_string("assert_condition", g_assert_condition
);
224 jf
.dump_string("assert_func", g_assert_func
);
227 jf
.dump_string("assert_file", g_assert_file
);
230 jf
.dump_unsigned("assert_line", g_assert_line
);
232 if (g_assert_thread_name
[0]) {
233 jf
.dump_string("assert_thread_name", g_assert_thread_name
);
235 if (g_assert_msg
[0]) {
236 jf
.dump_string("assert_msg", g_assert_msg
);
241 jf
.dump_bool("io_error", true);
242 if (g_eio_devname
[0]) {
243 jf
.dump_string("io_error_devname", g_eio_devname
);
246 jf
.dump_string("io_error_path", g_eio_path
);
249 jf
.dump_int("io_error_code", g_eio_error
);
252 jf
.dump_int("io_error_optype", g_eio_iotype
);
255 jf
.dump_unsigned("io_error_offset", g_eio_offset
);
258 jf
.dump_unsigned("io_error_length", g_eio_length
);
265 for (auto& i
: *extra
) {
266 jf
.dump_string(i
.first
, i
.second
);
273 string s
= oss
.str();
274 r
= safe_write(fd
, s
.c_str(), s
.size());
278 snprintf(fn
, sizeof(fn
)-1, "%s/done", base
);
284 static void handle_oneshot_fatal_signal(int signum
)
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
);
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.
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
));
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(),
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(),
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.
328 dout_emergency(oss
.str());
330 char crash_base
[PATH_MAX
] = { 0 };
332 generate_crash_dump(crash_base
, bt
);
334 // avoid recursion back into logging code if that is where
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
;
343 *_dout
<< " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
344 << "is needed to interpret this.\n"
347 g_ceph_context
->_log
->dump_recent();
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();
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.
363 reraise_fatal(signum
);
367 void install_standard_sighandlers(void)
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
);
381 /// --- safe handler ---
383 #include "common/Thread.h"
389 string
get_name_by_pid(pid_t pid
)
391 char buf
[PROC_PIDPATHINFO_MAXSIZE
];
392 int ret
= proc_pidpath(pid
, buf
, sizeof(buf
));
394 derr
<< "Fail to proc_pidpath(" << pid
<< ")"
395 << " error = " << cpp_strerror(ret
)
399 return string(buf
, ret
);
402 string
get_name_by_pid(pid_t pid
)
404 // If the PID is 0, its means the sender is the Kernel itself
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
);
414 derr
<< "Fail to open '" << proc_pid_path
415 << "' error = " << cpp_strerror(fd
)
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
));
426 derr
<< "Fail to read '" << proc_pid_path
427 << "' error = " << cpp_strerror(ret
)
431 std::replace(buf
, buf
+ ret
, '\0', ' ');
432 return string(buf
, ret
);
437 * safe async signal handler / dispatcher
439 * This is an async unix signal handler based on the design from
441 * http://evbergen.home.xs4all.nl/unix-signals.html
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.
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]
453 /// to signal shutdown
456 /// for an individual signal
457 struct safe_handler
{
460 memset(pipefd
, 0, sizeof(pipefd
));
461 memset(&handler
, 0, sizeof(handler
));
462 memset(&info_t
, 0, sizeof(info_t
));
466 int pipefd
[2]; // write to [1], read from [0]
467 signal_handler_t handler
;
471 safe_handler
*handlers
[32] = {nullptr};
473 /// to protect the handlers array
474 ceph::mutex lock
= ceph::make_mutex("SignalHandler::lock");
477 // create signal pipe
478 int r
= pipe_cloexec(pipefd
, 0);
480 r
= fcntl(pipefd
[0], F_SETFL
, O_NONBLOCK
);
484 create("signal_handler");
487 ~SignalHandler() override
{
491 void signal_thread() {
492 int r
= write(pipefd
[1], "\0", 1);
502 // thread entry point
503 void *entry() override
{
506 struct pollfd fds
[33];
510 fds
[num_fds
].fd
= pipefd
[0];
511 fds
[num_fds
].events
= POLLIN
| POLLERR
;
512 fds
[num_fds
].revents
= 0;
514 for (unsigned i
=0; i
<32; i
++) {
516 fds
[num_fds
].fd
= handlers
[i
]->pipefd
[0];
517 fds
[num_fds
].events
= POLLIN
| POLLERR
;
518 fds
[num_fds
].revents
= 0;
524 // wait for data on any of those pipes
525 int r
= poll(fds
, num_fds
, -1);
531 // consume byte from signal socket, if any.
532 TEMP_FAILURE_RETRY(read(pipefd
[0], &v
, 1));
535 for (unsigned signum
=0; signum
<32; signum
++) {
536 if (handlers
[signum
]) {
537 r
= read(handlers
[signum
]->pipefd
[0], &v
, 1);
539 siginfo_t
* siginfo
= &handlers
[signum
]->info_t
;
540 ostringstream message
;
541 message
<< "received signal: " << sig_str(signum
);
542 switch (siginfo
->si_code
) {
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
<< ")";
549 message
<< " ( Could be generated by pthread_kill(), raise(), abort(), alarm() )";
551 message
<< " UID: " << siginfo
->si_uid
;
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
;
565 derr
<< message
.str() << dendl
;
566 handlers
[signum
]->handler(signum
);
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
581 ceph_assert(handlers
[signum
]);
582 int r
= write(handlers
[signum
]->pipefd
[1], " ", 1);
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
591 ceph_assert(handlers
[signum
]);
592 memcpy(&handlers
[signum
]->info_t
, siginfo
, sizeof(siginfo_t
));
593 int r
= write(handlers
[signum
]->pipefd
[1], " ", 1);
597 void register_handler(int signum
, signal_handler_t handler
, bool oneshot
);
598 void unregister_handler(int signum
, signal_handler_t handler
);
601 static SignalHandler
*g_signal_handler
= NULL
;
603 static void handler_signal_hook(int signum
, siginfo_t
* siginfo
, void * content
) {
604 g_signal_handler
->queue_signal_info(signum
, siginfo
, content
);
607 void SignalHandler::register_handler(int signum
, signal_handler_t handler
, bool oneshot
)
611 ceph_assert(signum
>= 0 && signum
< 32);
613 safe_handler
*h
= new safe_handler
;
615 r
= pipe_cloexec(h
->pipefd
, 0);
617 r
= fcntl(h
->pipefd
[0], F_SETFL
, O_NONBLOCK
);
620 h
->handler
= handler
;
622 handlers
[signum
] = h
;
625 // signal thread so that it sees our new handler
628 // install our handler
629 struct sigaction oldact
;
630 struct sigaction act
;
631 memset(&act
, 0, sizeof(act
));
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);
640 void SignalHandler::unregister_handler(int signum
, signal_handler_t handler
)
642 ceph_assert(signum
>= 0 && signum
< 32);
643 safe_handler
*h
= handlers
[signum
];
645 ceph_assert(h
->handler
== handler
);
647 // restore to default
648 signal(signum
, SIG_DFL
);
650 // _then_ remove our handlers entry
652 handlers
[signum
] = NULL
;
655 // this will wake up select() so that worker thread sees our handler is gone
664 void init_async_signal_handler()
666 ceph_assert(!g_signal_handler
);
667 g_signal_handler
= new SignalHandler
;
670 void shutdown_async_signal_handler()
672 ceph_assert(g_signal_handler
);
673 delete g_signal_handler
;
674 g_signal_handler
= NULL
;
677 void queue_async_signal(int signum
)
679 ceph_assert(g_signal_handler
);
680 g_signal_handler
->queue_signal(signum
);
683 void register_async_signal_handler(int signum
, signal_handler_t handler
)
685 ceph_assert(g_signal_handler
);
686 g_signal_handler
->register_handler(signum
, handler
, false);
689 void register_async_signal_handler_oneshot(int signum
, signal_handler_t handler
)
691 ceph_assert(g_signal_handler
);
692 g_signal_handler
->register_handler(signum
, handler
, true);
695 void unregister_async_signal_handler(int signum
, signal_handler_t handler
)
697 ceph_assert(g_signal_handler
);
698 g_signal_handler
->unregister_handler(signum
, handler
);