From 4552994da9bdeacc42d26e37281023e8f1d17ec4 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Fri, 22 Jun 2018 18:45:49 +0100 Subject: [PATCH] Add "signal-process-only" option to avoid signalling process group. --- doc/manpages/dinit-service.5 | 4 ++++ src/baseproc-service.cc | 17 +++++++++++------ src/includes/service.h | 7 ++++--- src/load-service.cc | 3 +++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/doc/manpages/dinit-service.5 b/doc/manpages/dinit-service.5 index 4c735b8..f1be58d 100644 --- a/doc/manpages/dinit-service.5 +++ b/doc/manpages/dinit-service.5 @@ -272,6 +272,10 @@ For scripted services, indicates that if the service startup process terminates via an interrupt signal (SIGINT), then the service should be considered started. Note that if the interrupt was issued by Dinit to cancel startup, the service will instead be considered stopped. +.TP +\fBsignal-process-only\fR +Signal the service process only, rather than its entire process group, whenever +sending it a signal for any reason. .RE .LP The next section contains example service descriptions including some of the diff --git a/src/baseproc-service.cc b/src/baseproc-service.cc index 14d9f2a..42f603d 100644 --- a/src/baseproc-service.cc +++ b/src/baseproc-service.cc @@ -287,13 +287,18 @@ void base_process_service::kill_with_fire() noexcept void base_process_service::kill_pg(int signo) noexcept { - pid_t pgid = bp_sys::getpgid(pid); - if (pgid == -1) { - // only should happen if pid is invalid, which should never happen... - log(loglevel_t::ERROR, get_name(), ": can't signal process: ", strerror(errno)); - return; + if (onstart_flags.signal_process_only) { + bp_sys::kill(pid, signo); + } + else { + pid_t pgid = bp_sys::getpgid(pid); + if (pgid == -1) { + // only should happen if pid is invalid, which should never happen... + log(loglevel_t::ERROR, get_name(), ": can't signal process: ", strerror(errno)); + return; + } + bp_sys::kill(-pgid, signo); } - bp_sys::kill(-pgid, signo); } void base_process_service::timer_expired() noexcept diff --git a/src/includes/service.h b/src/includes/service.h index 6585028..bc3becc 100644 --- a/src/includes/service.h +++ b/src/includes/service.h @@ -122,10 +122,11 @@ struct service_flags_t { bool pass_cs_fd : 1; // pass this service a control socket connection via fd bool start_interruptible : 1; // the startup of this service process is ok to interrupt with SIGINT bool skippable : 1; // if interrupted the service is skipped (scripted services) + bool signal_process_only : 1; // signal the session process, not the whole group - service_flags_t() noexcept : rw_ready(false), log_ready(false), - no_sigterm(false), runs_on_console(false), starts_on_console(false), - pass_cs_fd(false), start_interruptible(false), skippable(false) + service_flags_t() noexcept : rw_ready(false), log_ready(false), no_sigterm(false), + runs_on_console(false), starts_on_console(false), pass_cs_fd(false), + start_interruptible(false), skippable(false), signal_process_only(false) { } }; diff --git a/src/load-service.cc b/src/load-service.cc index b26d318..30ce03a 100644 --- a/src/load-service.cc +++ b/src/load-service.cc @@ -607,6 +607,9 @@ service_record * dirload_service_set::load_service(const char * name) else if (option_txt == "skippable") { onstart_flags.skippable = true; } + else if (option_txt == "signal-process-only") { + onstart_flags.signal_process_only = true; + } else { throw service_description_exc(name, "Unknown option: " + option_txt); } -- 2.25.1