1*da0073e9SAndroid Build Coastguard Worker #pragma once 2*da0073e9SAndroid Build Coastguard Worker 3*da0073e9SAndroid Build Coastguard Worker #include <atomic> 4*da0073e9SAndroid Build Coastguard Worker #include <condition_variable> 5*da0073e9SAndroid Build Coastguard Worker #include <csignal> 6*da0073e9SAndroid Build Coastguard Worker #include <cstdint> 7*da0073e9SAndroid Build Coastguard Worker #include <mutex> 8*da0073e9SAndroid Build Coastguard Worker 9*da0073e9SAndroid Build Coastguard Worker #include <c10/macros/Export.h> 10*da0073e9SAndroid Build Coastguard Worker 11*da0073e9SAndroid Build Coastguard Worker #if defined(__APPLE__) 12*da0073e9SAndroid Build Coastguard Worker #define C10_SUPPORTS_SIGNAL_HANDLER 13*da0073e9SAndroid Build Coastguard Worker #elif defined(__linux__) && !defined(C10_DISABLE_SIGNAL_HANDLERS) 14*da0073e9SAndroid Build Coastguard Worker #define C10_SUPPORTS_FATAL_SIGNAL_HANDLERS 15*da0073e9SAndroid Build Coastguard Worker #define C10_SUPPORTS_SIGNAL_HANDLER 16*da0073e9SAndroid Build Coastguard Worker #endif 17*da0073e9SAndroid Build Coastguard Worker 18*da0073e9SAndroid Build Coastguard Worker #if defined(C10_SUPPORTS_FATAL_SIGNAL_HANDLERS) 19*da0073e9SAndroid Build Coastguard Worker #include <pthread.h> 20*da0073e9SAndroid Build Coastguard Worker #endif 21*da0073e9SAndroid Build Coastguard Worker 22*da0073e9SAndroid Build Coastguard Worker namespace c10 { 23*da0073e9SAndroid Build Coastguard Worker 24*da0073e9SAndroid Build Coastguard Worker class C10_API SignalHandler { 25*da0073e9SAndroid Build Coastguard Worker public: 26*da0073e9SAndroid Build Coastguard Worker enum class Action { NONE, STOP }; 27*da0073e9SAndroid Build Coastguard Worker 28*da0073e9SAndroid Build Coastguard Worker // Constructor. Specify what action to take when a signal is received. 29*da0073e9SAndroid Build Coastguard Worker SignalHandler(Action SIGINT_action, Action SIGHUP_action); 30*da0073e9SAndroid Build Coastguard Worker ~SignalHandler(); 31*da0073e9SAndroid Build Coastguard Worker 32*da0073e9SAndroid Build Coastguard Worker Action CheckForSignals(); 33*da0073e9SAndroid Build Coastguard Worker 34*da0073e9SAndroid Build Coastguard Worker bool GotSIGINT(); 35*da0073e9SAndroid Build Coastguard Worker bool GotSIGHUP(); 36*da0073e9SAndroid Build Coastguard Worker 37*da0073e9SAndroid Build Coastguard Worker Action SIGINT_action_; 38*da0073e9SAndroid Build Coastguard Worker Action SIGHUP_action_; 39*da0073e9SAndroid Build Coastguard Worker std::atomic<uint64_t> my_sigint_count_; 40*da0073e9SAndroid Build Coastguard Worker std::atomic<uint64_t> my_sighup_count_; 41*da0073e9SAndroid Build Coastguard Worker }; 42*da0073e9SAndroid Build Coastguard Worker 43*da0073e9SAndroid Build Coastguard Worker #if defined(C10_SUPPORTS_FATAL_SIGNAL_HANDLERS) 44*da0073e9SAndroid Build Coastguard Worker class C10_API FatalSignalHandler { 45*da0073e9SAndroid Build Coastguard Worker // This works by setting up certain fatal signal handlers. Previous fatal 46*da0073e9SAndroid Build Coastguard Worker // signal handlers will still be called when the signal is raised. Defaults 47*da0073e9SAndroid Build Coastguard Worker // to being off. 48*da0073e9SAndroid Build Coastguard Worker public: 49*da0073e9SAndroid Build Coastguard Worker C10_API void setPrintStackTracesOnFatalSignal(bool print); 50*da0073e9SAndroid Build Coastguard Worker C10_API bool printStackTracesOnFatalSignal(); 51*da0073e9SAndroid Build Coastguard Worker static FatalSignalHandler& getInstance(); 52*da0073e9SAndroid Build Coastguard Worker virtual ~FatalSignalHandler(); 53*da0073e9SAndroid Build Coastguard Worker 54*da0073e9SAndroid Build Coastguard Worker protected: 55*da0073e9SAndroid Build Coastguard Worker explicit FatalSignalHandler(); 56*da0073e9SAndroid Build Coastguard Worker 57*da0073e9SAndroid Build Coastguard Worker private: 58*da0073e9SAndroid Build Coastguard Worker void installFatalSignalHandlers(); 59*da0073e9SAndroid Build Coastguard Worker void uninstallFatalSignalHandlers(); 60*da0073e9SAndroid Build Coastguard Worker static void fatalSignalHandlerStatic(int signum); 61*da0073e9SAndroid Build Coastguard Worker void fatalSignalHandler(int signum); 62*da0073e9SAndroid Build Coastguard Worker virtual void fatalSignalHandlerPostProcess(); 63*da0073e9SAndroid Build Coastguard Worker struct sigaction* getPreviousSigaction(int signum); 64*da0073e9SAndroid Build Coastguard Worker const char* getSignalName(int signum); 65*da0073e9SAndroid Build Coastguard Worker void callPreviousSignalHandler( 66*da0073e9SAndroid Build Coastguard Worker struct sigaction* action, 67*da0073e9SAndroid Build Coastguard Worker int signum, 68*da0073e9SAndroid Build Coastguard Worker siginfo_t* info, 69*da0073e9SAndroid Build Coastguard Worker void* ctx); 70*da0073e9SAndroid Build Coastguard Worker void stacktraceSignalHandler(bool needsLock); 71*da0073e9SAndroid Build Coastguard Worker static void stacktraceSignalHandlerStatic( 72*da0073e9SAndroid Build Coastguard Worker int signum, 73*da0073e9SAndroid Build Coastguard Worker siginfo_t* info, 74*da0073e9SAndroid Build Coastguard Worker void* ctx); 75*da0073e9SAndroid Build Coastguard Worker void stacktraceSignalHandler(int signum, siginfo_t* info, void* ctx); 76*da0073e9SAndroid Build Coastguard Worker 77*da0073e9SAndroid Build Coastguard Worker // The mutex protects the bool. 78*da0073e9SAndroid Build Coastguard Worker std::mutex fatalSignalHandlersInstallationMutex; 79*da0073e9SAndroid Build Coastguard Worker bool fatalSignalHandlersInstalled; 80*da0073e9SAndroid Build Coastguard Worker // We need to hold a reference to call the previous SIGUSR2 handler in case 81*da0073e9SAndroid Build Coastguard Worker // we didn't signal it 82*da0073e9SAndroid Build Coastguard Worker struct sigaction previousSigusr2 {}; 83*da0073e9SAndroid Build Coastguard Worker // Flag dictating whether the SIGUSR2 handler falls back to previous handlers 84*da0073e9SAndroid Build Coastguard Worker // or is intercepted in order to print a stack trace. 85*da0073e9SAndroid Build Coastguard Worker std::atomic<bool> fatalSignalReceived; 86*da0073e9SAndroid Build Coastguard Worker // Global state set when a fatal signal is received so that backtracing 87*da0073e9SAndroid Build Coastguard Worker // threads know why they're printing a stacktrace. 88*da0073e9SAndroid Build Coastguard Worker const char* fatalSignalName; 89*da0073e9SAndroid Build Coastguard Worker int fatalSignum = -1; 90*da0073e9SAndroid Build Coastguard Worker // This wait condition is used to wait for other threads to finish writing 91*da0073e9SAndroid Build Coastguard Worker // their stack trace when in fatal sig handler (we can't use pthread_join 92*da0073e9SAndroid Build Coastguard Worker // because there's no way to convert from a tid to a pthread_t). 93*da0073e9SAndroid Build Coastguard Worker std::condition_variable writingCond; 94*da0073e9SAndroid Build Coastguard Worker std::mutex writingMutex; 95*da0073e9SAndroid Build Coastguard Worker // used to indicate if the other thread responded to the signal 96*da0073e9SAndroid Build Coastguard Worker bool signalReceived; 97*da0073e9SAndroid Build Coastguard Worker 98*da0073e9SAndroid Build Coastguard Worker struct signal_handler { 99*da0073e9SAndroid Build Coastguard Worker const char* name; 100*da0073e9SAndroid Build Coastguard Worker int signum; 101*da0073e9SAndroid Build Coastguard Worker struct sigaction previous; 102*da0073e9SAndroid Build Coastguard Worker }; 103*da0073e9SAndroid Build Coastguard Worker 104*da0073e9SAndroid Build Coastguard Worker // NOLINTNEXTLINE(*c-arrays*) 105*da0073e9SAndroid Build Coastguard Worker static signal_handler kSignalHandlers[]; 106*da0073e9SAndroid Build Coastguard Worker }; 107*da0073e9SAndroid Build Coastguard Worker 108*da0073e9SAndroid Build Coastguard Worker #endif // defined(C10_SUPPORTS_SIGNAL_HANDLER) 109*da0073e9SAndroid Build Coastguard Worker 110*da0073e9SAndroid Build Coastguard Worker } // namespace c10 111