mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-10 16:26:18 +02:00
105 lines
2.3 KiB
C++
105 lines
2.3 KiB
C++
|
#pragma once
|
||
|
///@file
|
||
|
|
||
|
#include "types.hh"
|
||
|
#include "error.hh"
|
||
|
#include "logging.hh"
|
||
|
#include "ansicolor.hh"
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <dirent.h>
|
||
|
#include <unistd.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
#include <boost/lexical_cast.hpp>
|
||
|
|
||
|
#include <atomic>
|
||
|
#include <functional>
|
||
|
#include <map>
|
||
|
#include <sstream>
|
||
|
#include <optional>
|
||
|
|
||
|
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);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 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();
|
||
|
|
||
|
/**
|
||
|
* To use in a process that already called `startSignalHandlerThread()`
|
||
|
* or `saveSignalMask()` first.
|
||
|
*/
|
||
|
void restoreSignals();
|
||
|
|
||
|
/**
|
||
|
* 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); }))
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
|
||
|
}
|