#include "signals.hh" #include "looper.hh" #include "unique_pipe.hh" #include #include #include #include #include #include #include #include namespace signals { namespace { std::unordered_map g_fds; int signum(Signal signal) { switch (signal) { case Signal::INT: return SIGINT; case Signal::TERM: return SIGTERM; } std::unreachable(); } void signal_handler(int signum) { auto it = g_fds.find(signum); if (it != g_fds.end()) { char c = 1; while (true) { auto ret = write(it->second, &c, 1); if (ret < 0 && errno == EINTR) continue; break; } } } class HandlerImpl : public Handler { public: HandlerImpl(looper::Looper& looper, Signal signal, std::function callback) : looper_(looper), signal_(signum(signal)), callback_(std::move(callback)) { looper_.add(pipe_.reader(), looper::EVENT_READ, [this](auto event) { call(event); }); g_fds[signal_] = pipe_.writer(); ::signal(signal_, signal_handler); } ~HandlerImpl() override { ::signal(signal_, SIG_DFL); looper_.remove(pipe_.reader()); g_fds.erase(signal_); } private: void call(uint8_t /* event */) { char buf[10]; while (true) { auto ret = read(pipe_.reader(), buf, 10); if (ret < 0 && errno == EINTR) continue; break; } callback_(); } unique_pipe pipe_; looper::Looper& looper_; int signal_; std::function callback_; }; } // namespace std::unique_ptr Handler::create(looper::Looper& looper, Signal signal, std::function callback) { return std::make_unique(looper, signal, std::move(callback)); } } // namespace signals