Fix interrupt handling
This commit is contained in:
parent
951357e5fb
commit
83ae6503e8
|
@ -97,6 +97,9 @@ static void opensslLockCallback(int mode, int type, const char * file, int line)
|
|||
}
|
||||
|
||||
|
||||
static void sigHandler(int signo) { }
|
||||
|
||||
|
||||
void initNix()
|
||||
{
|
||||
/* Turn on buffering for cerr. */
|
||||
|
@ -130,6 +133,10 @@ void initNix()
|
|||
if (sigaction(SIGCHLD, &act, 0))
|
||||
throw SysError("resetting SIGCHLD");
|
||||
|
||||
/* Install a dummy SIGUSR1 handler for use with pthread_kill(). */
|
||||
act.sa_handler = sigHandler;
|
||||
if (sigaction(SIGUSR1, &act, 0)) throw SysError("handling SIGUSR1");
|
||||
|
||||
/* Register a SIGSEGV handler to detect stack overflows. */
|
||||
detectStackOverflow();
|
||||
|
||||
|
@ -253,6 +260,8 @@ void showManPage(const string & name)
|
|||
|
||||
int handleExceptions(const string & programName, std::function<void()> fun)
|
||||
{
|
||||
ReceiveInterrupts receiveInterrupts; // FIXME: need better place for this
|
||||
|
||||
string error = ANSI_RED "error:" ANSI_NORMAL " ";
|
||||
try {
|
||||
try {
|
||||
|
|
|
@ -27,8 +27,7 @@ public:
|
|||
fds[0].events = 0;
|
||||
if (poll(fds, 1, -1) == -1) abort(); // can't happen
|
||||
assert(fds[0].revents & POLLHUP);
|
||||
/* We got POLLHUP, so send an INT signal to the main thread. */
|
||||
kill(getpid(), SIGINT);
|
||||
triggerInterrupt();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -1197,18 +1197,22 @@ static void signalHandlerThread(sigset_t set)
|
|||
int signal = 0;
|
||||
sigwait(&set, &signal);
|
||||
|
||||
if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) {
|
||||
_isInterrupted = 1;
|
||||
if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP)
|
||||
triggerInterrupt();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto interruptCallbacks(_interruptCallbacks.lock());
|
||||
for (auto & callback : *interruptCallbacks) {
|
||||
try {
|
||||
callback();
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
void triggerInterrupt()
|
||||
{
|
||||
_isInterrupted = 1;
|
||||
|
||||
{
|
||||
auto interruptCallbacks(_interruptCallbacks.lock());
|
||||
for (auto & callback : *interruptCallbacks) {
|
||||
try {
|
||||
callback();
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -433,5 +433,21 @@ struct InterruptCallback
|
|||
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); }))
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue