summaryrefslogtreecommitdiff
path: root/src/signal_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/signal_handler.cc')
-rw-r--r--src/signal_handler.cc75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/signal_handler.cc b/src/signal_handler.cc
new file mode 100644
index 0000000..7d64e60
--- /dev/null
+++ b/src/signal_handler.cc
@@ -0,0 +1,75 @@
+#include "common.hh"
+
+#include "io.hh"
+#include "looper.hh"
+#include "signal_handler.hh"
+#include "unique_pipe.hh"
+
+#include <signal.h>
+#include <unordered_map>
+
+namespace {
+
+std::unordered_map<int, int> g_fds;
+
+int signum(SignalHandler::Signal signal) {
+ switch (signal) {
+ case SignalHandler::Signal::INT:
+ return SIGINT;
+ case SignalHandler::Signal::TERM:
+ return SIGTERM;
+ case SignalHandler::Signal::HUP:
+ return SIGHUP;
+ }
+ assert(false);
+ return 0;
+}
+
+void signal_handler(int signum) {
+ auto it = g_fds.find(signum);
+ if (it != g_fds.end()) {
+ char c = 1;
+ io::write(it->second, &c, 1);
+ }
+}
+
+class SignalHandlerImpl : public SignalHandler {
+public:
+ SignalHandlerImpl(std::shared_ptr<Looper> looper, Signal signal,
+ std::function<void()> callback)
+ : looper_(looper), signal_(signum(signal)), callback_(std::move(callback)) {
+ looper_->add(pipe_.reader(), Looper::EVENT_READ,
+ std::bind(&SignalHandlerImpl::call, this,
+ std::placeholders::_1));
+ g_fds[signal_] = pipe_.writer();
+
+ ::signal(signal_, signal_handler);
+ }
+
+ ~SignalHandlerImpl() {
+ signal(signal_, SIG_DFL);
+ looper_->remove(pipe_.reader());
+ g_fds.erase(signal_);
+ }
+
+private:
+ void call(uint8_t) {
+ char buf[10];
+ io::read(pipe_.reader(), buf, 10);
+ callback_();
+ }
+
+ unique_pipe pipe_;
+ std::shared_ptr<Looper> looper_;
+ int signal_;
+ std::function<void()> callback_;
+};
+
+} // namespace
+
+std::unique_ptr<SignalHandler> SignalHandler::create(
+ std::shared_ptr<Looper> looper, Signal signal,
+ std::function<void()> callback) {
+ return std::make_unique<SignalHandlerImpl>(
+ std::move(looper), signal, std::move(callback));
+}