aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-01-25 13:37:02 +0100
committerEelco Dolstra <edolstra@gmail.com>2017-01-26 20:40:33 +0100
commit83ae6503e87c7f5237fb0f1602793c126436495a (patch)
treee439570378a11b6ec6d1ef381aed4b5e1613c5bb /src/libutil
parent951357e5fb4cd0804e729866f204b635add926a3 (diff)
Fix interrupt handling
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/monitor-fd.hh3
-rw-r--r--src/libutil/util.cc28
-rw-r--r--src/libutil/util.hh16
3 files changed, 33 insertions, 14 deletions
diff --git a/src/libutil/monitor-fd.hh b/src/libutil/monitor-fd.hh
index 6f01ccd91..e0ec66c01 100644
--- a/src/libutil/monitor-fd.hh
+++ b/src/libutil/monitor-fd.hh
@@ -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();
});
};
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 52608ac2a..ca4edc2cd 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -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;
-
- {
- auto interruptCallbacks(_interruptCallbacks.lock());
- for (auto & callback : *interruptCallbacks) {
- try {
- callback();
- } catch (...) {
- ignoreException();
- }
- }
+ if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP)
+ triggerInterrupt();
+ }
+}
+
+void triggerInterrupt()
+{
+ _isInterrupted = 1;
+
+ {
+ auto interruptCallbacks(_interruptCallbacks.lock());
+ for (auto & callback : *interruptCallbacks) {
+ try {
+ callback();
+ } catch (...) {
+ ignoreException();
}
}
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index b68d48582..07141ffed 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -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); }))
+ { }
+};
+
}