daemon: use signalfd-based signal handling if available (#3778)
If signalfd(2) interface is available, prefer it over traditional signal handlers. This is mostly intended to drop dedicated signal handling thread and hook signal processing into libevent event loop in the most natural way. Signed-off-by: Dmitry Antipov <dantipov@cloudlinux.com> Signed-off-by: Dmitry Antipov <dantipov@cloudlinux.com>
This commit is contained in:
parent
2bcb8f8535
commit
050ee1cbbd
|
@ -539,6 +539,7 @@ endif()
|
|||
include(LargeFileSupport)
|
||||
|
||||
set(NEEDED_HEADERS
|
||||
sys/signalfd.h
|
||||
sys/statvfs.h
|
||||
xfs/xfs.h
|
||||
xlocale.h)
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#ifdef HAVE_SYS_SIGNALFD_H
|
||||
#include <event2/event.h>
|
||||
#include <sys/signalfd.h>
|
||||
#endif /* signalfd API */
|
||||
#include <signal.h>
|
||||
#include <stdlib.h> /* abort(), daemon(), exit() */
|
||||
#include <fcntl.h> /* open() */
|
||||
|
@ -30,7 +34,11 @@ 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 */
|
||||
|
||||
/***
|
||||
****
|
||||
|
@ -63,6 +71,55 @@ 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;
|
||||
|
||||
if (read(fd, &fdsi, sizeof(fdsi)) != sizeof(fdsi))
|
||||
assert("Error reading signal descriptor" && 0);
|
||||
else
|
||||
handle_signal(fdsi.ssi_signo);
|
||||
}
|
||||
|
||||
static bool setup_signals(void* arg)
|
||||
{
|
||||
sigset_t mask = {};
|
||||
struct event* sigev = nullptr;
|
||||
struct event_base* base = static_cast<struct event_base*>(arg);
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
sigaddset(&mask, SIGHUP);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0)
|
||||
return false;
|
||||
|
||||
sigfd = signalfd(-1, &mask, 0);
|
||||
if (sigfd < 0)
|
||||
return false;
|
||||
|
||||
sigev = event_new(base, sigfd, EV_READ | EV_PERSIST, handle_signals, nullptr);
|
||||
if (sigev == nullptr)
|
||||
{
|
||||
close(sigfd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event_add(sigev, nullptr) < 0)
|
||||
{
|
||||
event_del(sigev);
|
||||
close(sigfd);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else /* no signalfd API */
|
||||
|
||||
static void send_signal_to_pipe(int sig)
|
||||
{
|
||||
int const old_errno = errno;
|
||||
|
@ -142,6 +199,8 @@ static bool setup_signal_handler(int sig, tr_error** error)
|
|||
return true;
|
||||
}
|
||||
|
||||
#endif /* signalfd API */
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
@ -207,6 +266,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))
|
||||
|
@ -220,9 +280,14 @@ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exi
|
|||
return false;
|
||||
}
|
||||
|
||||
*exit_code = cb->on_start(cb_arg, foreground);
|
||||
*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;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ static DWORD WINAPI handle_service_ctrl(DWORD control_code, DWORD /*event_type*/
|
|||
|
||||
static unsigned int __stdcall service_thread_main(void* /*context*/)
|
||||
{
|
||||
return callbacks->on_start(callback_arg, false);
|
||||
return callbacks->on_start(callback_arg, nullptr, false);
|
||||
}
|
||||
|
||||
static VOID WINAPI service_main(DWORD /*argc*/, LPWSTR* /*argv*/)
|
||||
|
@ -238,7 +238,7 @@ bool dtr_daemon(dtr_callbacks const* cb, void* cb_arg, bool foreground, int* exi
|
|||
return false;
|
||||
}
|
||||
|
||||
*exit_code = cb->on_start(cb_arg, true);
|
||||
*exit_code = cb->on_start(cb_arg, nullptr, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -90,7 +90,7 @@ public:
|
|||
bool init(int argc, char* argv[], bool* foreground, int* ret);
|
||||
bool parseArgs(int argc, char const** argv, bool* dump_settings, bool* foreground, int* exit_code);
|
||||
bool reopenLogFile(char const* filename);
|
||||
int start(bool foreground);
|
||||
int start(bool (*setupsigfn)(void*), bool foreground);
|
||||
void periodicUpdate();
|
||||
void reportStatus();
|
||||
void reconfigure();
|
||||
|
@ -731,7 +731,7 @@ void Daemon::stop(void)
|
|||
event_base_loopexit(ev_base_, nullptr);
|
||||
}
|
||||
|
||||
int Daemon::start(bool foreground)
|
||||
int Daemon::start(bool (*setupsigfn)(void*), bool foreground)
|
||||
{
|
||||
bool boolVal;
|
||||
bool pidfile_created = false;
|
||||
|
@ -748,7 +748,7 @@ int Daemon::start(bool foreground)
|
|||
/* setup event state */
|
||||
ev_base_ = event_base_new();
|
||||
|
||||
if (ev_base_ == nullptr)
|
||||
if (ev_base_ == nullptr || (setupsigfn ? setupsigfn(ev_base_) : true) == false)
|
||||
{
|
||||
auto const error_code = errno;
|
||||
auto const errmsg = fmt::format(
|
||||
|
@ -937,9 +937,9 @@ CLEANUP:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int daemon_start(void* varg, bool foreground)
|
||||
static int daemon_start(void* varg, bool (*setupsigfn)(void*), bool foreground)
|
||||
{
|
||||
return static_cast<Daemon*>(varg)->start(foreground);
|
||||
return static_cast<Daemon*>(varg)->start(setupsigfn, foreground);
|
||||
}
|
||||
|
||||
bool Daemon::init(int argc, char* argv[], bool* foreground, int* ret)
|
||||
|
|
|
@ -9,7 +9,7 @@ struct tr_error;
|
|||
|
||||
typedef struct dtr_callbacks
|
||||
{
|
||||
int (*on_start)(void* arg, bool foreground);
|
||||
int (*on_start)(void* arg, bool (*setupsigfn)(void*), bool foreground);
|
||||
void (*on_stop)(void* arg);
|
||||
void (*on_reconfigure)(void* arg);
|
||||
} dtr_callbacks;
|
||||
|
|
Loading…
Reference in New Issue