1#include <csignal>
2
3#include "taichi/common/logging.h"
4#include "taichi/system/hacked_signal_handler.h"
5#include "taichi/system/threading.h"
6#include "taichi/system/traceback.h"
7
8namespace taichi {
9namespace {
10
11std::string signal_name(int sig) {
12#if !defined(_WIN64)
13 return strsignal(sig);
14#else
15 if (sig == SIGABRT) {
16 return "SIGABRT";
17 } else if (sig == SIGFPE) {
18 return "SIGFPE";
19 } else if (sig == SIGILL) {
20 return "SIGFPE";
21 } else if (sig == SIGSEGV) {
22 return "SIGSEGV";
23 } else if (sig == SIGTERM) {
24 return "SIGTERM";
25 } else {
26 return "SIGNAL-Unknown";
27 }
28#endif
29}
30
31void signal_handler(int signo) {
32 // It seems that there's no way to pass exception to Python in signal
33 // handlers?
34 // @archibate found that in fact there are such solution:
35 // https://docs.python.org/3/library/faulthandler.html#module-faulthandler
36 auto sig_name = signal_name(signo);
37 Logger::get_instance().error(
38 fmt::format("Received signal {} ({})", signo, sig_name), false);
39 exit(-1);
40 TI_UNREACHABLE;
41}
42
43} // namespace
44
45HackedSignalRegister::HackedSignalRegister() {
46#define TI_REGISTER_SIGNAL_HANDLER(name, handler) \
47 { \
48 if (std::signal(name, handler) == SIG_ERR) \
49 std::printf("Cannot register signal handler for" #name "\n"); \
50 }
51
52 TI_REGISTER_SIGNAL_HANDLER(SIGSEGV, signal_handler);
53 TI_REGISTER_SIGNAL_HANDLER(SIGABRT, signal_handler);
54#if !defined(_WIN64)
55 TI_REGISTER_SIGNAL_HANDLER(SIGBUS, signal_handler);
56#endif
57 TI_REGISTER_SIGNAL_HANDLER(SIGFPE, signal_handler);
58
59#undef TI_REGISTER_SIGNAL_HANDLER
60
61 Logger::get_instance().set_print_stacktrace_func(print_traceback);
62 TI_TRACE("Taichi signal handlers registered. Thread ID = {}", PID::get_pid());
63}
64
65HackedSignalRegister::~HackedSignalRegister() {
66#define TI_UNREGISTER_SIGNAL_HANDLER(name) \
67 { \
68 if (std::signal(name, SIG_DFL) == SIG_ERR) \
69 std::printf("Cannot unregister signal handler for" #name "\n"); \
70 }
71
72 TI_UNREGISTER_SIGNAL_HANDLER(SIGSEGV);
73 TI_UNREGISTER_SIGNAL_HANDLER(SIGABRT);
74#if !defined(_WIN64)
75 TI_UNREGISTER_SIGNAL_HANDLER(SIGBUS);
76#endif
77 TI_UNREGISTER_SIGNAL_HANDLER(SIGFPE);
78
79#undef TI_UNREGISTER_SIGNAL_HANDLER
80 TI_TRACE("Taichi signal handlers unregistered. Thread ID = {}",
81 PID::get_pid());
82}
83
84} // namespace taichi
85