#include "signals.hh" #include "looper.hh" #include "unique_fd.hh" #include #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()) { uint64_t c = 1; while (true) { auto ret = write(it->second, &c, sizeof(c)); if (ret < 0 && errno == EINTR) continue; break; } } } class HandlerImpl : public Handler { public: HandlerImpl(looper::Looper& looper, Signal signal, std::function callback) : fd_{eventfd(0, 0)}, looper_(looper), signal_(signum(signal)), callback_(std::move(callback)) { looper_.add(fd_.get(), looper::EVENT_READ, [this](auto event) { call(event); }); g_fds[signal_] = fd_.get(); ::signal(signal_, signal_handler); } ~HandlerImpl() override { ::signal(signal_, SIG_DFL); looper_.remove(fd_.get()); g_fds.erase(signal_); } private: void call(uint8_t /* event */) { uint64_t c; while (true) { auto ret = read(fd_.get(), &c, sizeof(c)); if (ret < 0 && errno == EINTR) continue; break; } callback_(); } unique_fd fd_; 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