diff --git a/daemon/daemon-posix.cc b/daemon/daemon-posix.cc index 7b4aeacfb..3ba41e48b 100644 --- a/daemon/daemon-posix.cc +++ b/daemon/daemon-posix.cc @@ -7,9 +7,9 @@ #include #include #ifdef HAVE_SYS_SIGNALFD_H -#include #include #endif /* signalfd API */ +#include #include #include /* abort(), daemon(), exit() */ #include /* open() */ @@ -25,33 +25,17 @@ #include "daemon.h" -using namespace std::literals; - -/*** -**** -***/ - static dtr_callbacks const* callbacks = nullptr; static void* callback_arg = nullptr; -#ifdef HAVE_SYS_SIGNALFD_H -static int sigfd = -1; -#else -static int signal_pipe[2]; -#endif /* signalfd API */ - -/*** -**** -***/ - static void set_system_error(tr_error** error, int code, std::string_view message) { tr_error_set(error, code, fmt::format(FMT_STRING("{:s}: {:s} ({:d}"), message, tr_strerror(code), code)); } -/*** -**** -***/ +#ifdef HAVE_SYS_SIGNALFD_H + +static int sigfd = -1; static void handle_signal(int sig) { @@ -71,8 +55,6 @@ static void handle_signal(int sig) } } -#ifdef HAVE_SYS_SIGNALFD_H - static void handle_signals(evutil_socket_t fd, short /*what*/, void* /*arg*/) { struct signalfd_siginfo fdsi; @@ -118,92 +100,42 @@ static bool setup_signals(void* arg) return true; } -#else /* no signalfd API */ +#else /* no signalfd API, use evsignal */ -static void send_signal_to_pipe(int sig) +static void reconfigure(evutil_socket_t /*fd*/, short /*events*/, void* /*arg*/) { - int const old_errno = errno; - - if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) - { - abort(); - } - - errno = old_errno; + callbacks->on_reconfigure(callback_arg); } -static void* signal_handler_thread_main(void* /*arg*/) +static void stop(evutil_socket_t /*fd*/, short /*events*/, void* /*arg*/) { - int sig; - - while (read(signal_pipe[0], &sig, sizeof(sig)) == sizeof(sig) && sig != 0) - { - handle_signal(sig); - } - - return nullptr; + callbacks->on_stop(callback_arg); } -static bool create_signal_pipe(tr_error** error) +static bool setup_signal(struct event_base* base, int sig, void (*callback)(evutil_socket_t, short, void*)) { - if (pipe(signal_pipe) == -1) + struct event* sigev = evsignal_new(base, sig, callback, nullptr); + + if (sigev == nullptr) + return false; + + if (evsignal_add(sigev, nullptr) < 0) { - set_system_error(error, errno, "pipe() failed"); + event_free(sigev); return false; } return true; } -static void destroy_signal_pipe(void) +static bool setup_signals(void* arg) { - close(signal_pipe[0]); - close(signal_pipe[1]); + struct event_base* base = static_cast(arg); + + return (setup_signal(base, SIGHUP, reconfigure) && setup_signal(base, SIGINT, stop) && setup_signal(base, SIGTERM, stop)); } -static bool create_signal_handler_thread(pthread_t* thread, tr_error** error) -{ - if (!create_signal_pipe(error)) - { - return false; - } - - if ((errno = pthread_create(thread, nullptr, &signal_handler_thread_main, nullptr)) != 0) - { - set_system_error(error, errno, "pthread_create() failed"); - destroy_signal_pipe(); - return false; - } - - return true; -} - -static void destroy_signal_handler_thread(pthread_t thread) -{ - send_signal_to_pipe(0); - pthread_join(thread, nullptr); - - destroy_signal_pipe(); -} - -static bool setup_signal_handler(int sig, tr_error** error) -{ - assert(sig != 0); - - if (signal(sig, &send_signal_to_pipe) == SIG_ERR) - { - set_system_error(error, errno, "signal() failed"); - return false; - } - - return true; -} - -#endif /* signalfd API */ - -/*** -**** -***/ +#endif /* HAVE_SYS_SIGNALFD_H */ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exit_code, tr_error** error) { @@ -266,28 +198,7 @@ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exi #endif } -#ifndef HAVE_SYS_SIGNALFD_H - pthread_t signal_thread; - - if (!create_signal_handler_thread(&signal_thread, error)) - { - return false; - } - - if (!setup_signal_handler(SIGINT, error) || !setup_signal_handler(SIGTERM, error) || !setup_signal_handler(SIGHUP, error)) - { - destroy_signal_handler_thread(signal_thread); - return false; - } - - *exit_code = cb->on_start(cb_arg, nullptr, foreground); -#else *exit_code = cb->on_start(cb_arg, setup_signals, foreground); -#endif /* signalfd API */ - -#ifndef HAVE_SYS_SIGNALFD_H - destroy_signal_handler_thread(signal_thread); -#endif /* no signalfd API */ return true; }