diff options
author | Jade Lovelace <lix@jade.fyi> | 2024-03-09 22:36:47 -0800 |
---|---|---|
committer | Jade Lovelace <lix@jade.fyi> | 2024-03-11 00:52:09 -0700 |
commit | 8be7030299699edd3732411d8d97f237a67fbc08 (patch) | |
tree | 118f6c5c8dfac9ae9c65f54c5eb5942323324b17 /src/libutil/signals.hh | |
parent | a9b813cc3bcf89f03de0db96fc2e88d1c83b8303 (diff) |
util.hh: split out signals stuff
Copies part of the changes of ac89bb064aeea85a62b82a6daf0ecca7190a28b7
Change-Id: I9ce601875cd6d4db5eb1132d7835c5bab9f126d8
Diffstat (limited to 'src/libutil/signals.hh')
-rw-r--r-- | src/libutil/signals.hh | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/libutil/signals.hh b/src/libutil/signals.hh new file mode 100644 index 000000000..c58dc37cf --- /dev/null +++ b/src/libutil/signals.hh @@ -0,0 +1,93 @@ +#pragma once +/// @file + +#include "types.hh" +#include "error.hh" + +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <signal.h> + +#include <atomic> +#include <functional> +#include <sstream> + +namespace nix { + +/* User interruption. */ + +extern std::atomic<bool> _isInterrupted; + +extern thread_local std::function<bool()> interruptCheck; + +void setInterruptThrown(); + +void _interrupted(); + +void inline checkInterrupt() +{ + if (_isInterrupted || (interruptCheck && interruptCheck())) + _interrupted(); +} + +MakeError(Interrupted, BaseError); + +void restoreSignals(); + + +/** + * Start a thread that handles various signals. Also block those signals + * on the current thread (and thus any threads created by it). + * Saves the signal mask before changing the mask to block those signals. + * See saveSignalMask(). + */ +void startSignalHandlerThread(); + +/** + * Saves the signal mask, which is the signal mask that nix will restore + * before creating child processes. + * See setChildSignalMask() to set an arbitrary signal mask instead of the + * current mask. + */ +void saveSignalMask(); + +/** + * Sets the signal mask. Like saveSignalMask() but for a signal set that doesn't + * necessarily match the current thread's mask. + * See saveSignalMask() to set the saved mask to the current mask. + */ +void setChildSignalMask(sigset_t *sigs); + +struct InterruptCallback +{ + virtual ~InterruptCallback() { }; +}; + +/** + * Register a function that gets called on SIGINT (in a non-signal + * context). + */ +std::unique_ptr<InterruptCallback> createInterruptCallback( + std::function<void()> callback); + +void triggerInterrupt(); + +/** + * A RAII class that causes the current thread to receive SIGUSR1 when + * the signal handler thread receives SIGINT. That is, this allows + * SIGINT to be multiplexed to multiple threads. + */ +struct ReceiveInterrupts +{ + pthread_t target; + std::unique_ptr<InterruptCallback> callback; + + ReceiveInterrupts() + : target(pthread_self()) + , callback(createInterruptCallback([&]() { pthread_kill(target, SIGUSR1); })) + { } +}; + +}; |