RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
ControlCHandler.h
Go to the documentation of this file.
1//
2// Copyright (C) David Cosgrove 2025.
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10
11#ifndef CONTROLCHANDLER_H
12#define CONTROLCHANDLER_H
13
14#include <atomic>
15#include <csignal>
16#include <stdexcept>
17
18namespace RDKit {
19
20class ControlCCaught : public std::runtime_error {
21 public:
22 explicit ControlCCaught()
23 : std::runtime_error("The process was interrupted with Ctrl+c") {};
24};
25
26//! This class catches a control-C/SIGINT and sets the flag d_gotSignal
27//! if one is received. It is intended to be used inside a long
28//! C++ calculation called from Python which intercepts the signal
29//! handler. The C++ code must check the value of d_gotSignal
30//! periodically and act accordingly. The destructor resets
31//! the signal handler and flag for next use, which is essential
32//! because it's a static variable.
33//! Example usage, inside a boost::python wrapper:
34//! ResultsObject results;
35//! {
36//! NOGIL gil;
37//! results = someFunction();
38//! }
39//! if (results.getCancelled()) {
40//! throw_runtime_error("someFunction cancelled");
41//! }
42//! It's important that the exception is thrown once the GIL has been
43//! released, otherwise a crash is inevitable at some future point.
45 public:
46 ControlCHandler() { d_prev_handler = std::signal(SIGINT, signalHandler); }
52 std::signal(SIGINT, d_prev_handler);
53 d_gotSignal = false;
54 }
55 static bool getGotSignal() { return d_gotSignal; }
56 static void signalHandler(int signalNumber) {
57 if (signalNumber == SIGINT) {
58 d_gotSignal = true;
59 std::signal(SIGINT, d_prev_handler);
60 }
61 }
62 static void reset() {
63 d_gotSignal = false;
64 std::signal(SIGINT, signalHandler);
65 }
66
67 private:
68 inline static bool d_gotSignal{false};
69 inline static void (*d_prev_handler)(int);
70};
71} // namespace RDKit
72#endif // CONTROLCHANDLER_H
ControlCHandler(ControlCHandler &&)=delete
ControlCHandler & operator=(ControlCHandler &&)=delete
ControlCHandler(const ControlCHandler &)=delete
ControlCHandler & operator=(const ControlCHandler &)=delete
static void signalHandler(int signalNumber)
Std stuff.