xref: /aosp_15_r20/external/pytorch/c10/util/signal_handler.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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