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 | |
8 | namespace taichi { |
9 | namespace { |
10 | |
11 | std::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 | |
31 | void 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 | |
45 | HackedSignalRegister::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 | |
65 | HackedSignalRegister::~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 | |