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