dReal4
signal_handler_guard.h
1 #pragma once
2 
3 #include <atomic>
4 #include <csignal>
5 
6 namespace dreal {
7 
8 /// Sets a new signal handler and restores the old one when it goes
9 /// out of scope. When the flag is set, its destructor clears it out.
10 ///
11 /// Motivation
12 /// ----------
13 ///
14 /// Python's signal handler merely set a flag which is only checked in
15 /// the next python instruction. As a result, "C/C++ code may run
16 /// uninterrupted for an arbitrary amount of time" (from :
17 /// https://docs.python.org/3/library/signal.html#execution-of-python-signal-handlers)
18 ///
19 /// Our approach
20 /// ------------
21 ///
22 /// We provide a custom signal handler for SIGINT, which sets a global
23 /// flag (g_interrupted) which is monitored inside of dReal code. When
24 /// the flag is set, the checking code is supposed to throw an
25 /// exception, which will terminate the C++ call gracefully. The C++
26 /// exception will be handled by pybind11, which will translate it to
27 /// a Python exception.
29  public:
30  using handler_t = void (*)(int);
31 
32  /// Registers the new handler and saves the current one.
33  SignalHandlerGuard(int sig, handler_t handler,
34  volatile std::atomic_bool* flag);
35  SignalHandlerGuard(const SignalHandlerGuard&) = delete;
37  SignalHandlerGuard& operator=(const SignalHandlerGuard&) = delete;
38  SignalHandlerGuard& operator=(SignalHandlerGuard&&) = delete;
39 
40  /// Restores the old signal handler. If the flag is set, clear it.
42 
43  private:
44  const int sig_{0};
45  volatile std::atomic_bool* flag_;
46 
47  using sigaction_t = struct sigaction;
48  sigaction_t old_action_;
49 };
50 } // namespace dreal
Sum type of symbolic::Expression and symbolic::Formula.
Definition: api.cc:9
SignalHandlerGuard(int sig, handler_t handler, volatile std::atomic_bool *flag)
Registers the new handler and saves the current one.
Definition: signal_handler_guard.cc:10
Sets a new signal handler and restores the old one when it goes out of scope.
Definition: signal_handler_guard.h:28
~SignalHandlerGuard()
Restores the old signal handler. If the flag is set, clear it.
Definition: signal_handler_guard.cc:24