mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
core: add support for RestartKillSignal= to override signal used for restart jobs
v2: - if RestartKillSignal= is not specified, fall back to KillSignal=. This is necessary to preserve backwards compatibility (and keep KillSignal= generally useful).
This commit is contained in:
parent
28a2dfe801
commit
a232ebcc2c
@ -80,7 +80,7 @@ _systemd_run() {
|
||||
SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group=
|
||||
DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth=
|
||||
BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment=
|
||||
KillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
|
||||
KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
|
||||
LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC=
|
||||
LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE=
|
||||
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices=
|
||||
|
@ -35,7 +35,7 @@ _arguments \
|
||||
SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \
|
||||
DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \
|
||||
BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \
|
||||
KillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
|
||||
KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
|
||||
LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \
|
||||
LimitMEMLOCK= LimitLOCKS= LimitSIGPENDING= LimitMSGQUEUE= \
|
||||
LimitNICE= LimitRTPRIO= LimitRTTIME= PrivateTmp= PrivateDevices= \
|
||||
|
@ -8,10 +8,28 @@
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_kill_mode, kill_mode, KillMode);
|
||||
|
||||
static int property_get_restart_kill_signal(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
KillContext *c = userdata;
|
||||
int s;
|
||||
|
||||
assert(c);
|
||||
|
||||
s = restart_kill_signal(c);
|
||||
return sd_bus_message_append_basic(reply, 'i', &s);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_kill_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("KillMode", "s", property_get_kill_mode, offsetof(KillContext, kill_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("KillSignal", "i", bus_property_get_int, offsetof(KillContext, kill_signal), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RestartKillSignal", "i", property_get_restart_kill_signal, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FinalKillSignal", "i", bus_property_get_int, offsetof(KillContext, final_kill_signal), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SendSIGKILL", "b", bus_property_get_bool, offsetof(KillContext, send_sigkill), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SendSIGHUP", "b", bus_property_get_bool, offsetof(KillContext, send_sighup), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -21,6 +39,7 @@ const sd_bus_vtable bus_kill_vtable[] = {
|
||||
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(kill_mode, KillMode, kill_mode_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(restart_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(final_kill_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(watchdog_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
|
||||
@ -51,6 +70,9 @@ int bus_kill_context_set_transient_property(
|
||||
if (streq(name, "KillSignal"))
|
||||
return bus_set_transient_kill_signal(u, name, &c->kill_signal, message, flags, error);
|
||||
|
||||
if (streq(name, "RestartKillSignal"))
|
||||
return bus_set_transient_restart_kill_signal(u, name, &c->restart_kill_signal, message, flags, error);
|
||||
|
||||
if (streq(name, "FinalKillSignal"))
|
||||
return bus_set_transient_final_kill_signal(u, name, &c->final_kill_signal, message, flags, error);
|
||||
|
||||
|
@ -9,6 +9,7 @@ void kill_context_init(KillContext *c) {
|
||||
assert(c);
|
||||
|
||||
c->kill_signal = SIGTERM;
|
||||
/* restart_kill_signal is unset by default and we fall back to kill_signal */
|
||||
c->final_kill_signal = SIGKILL;
|
||||
c->send_sigkill = true;
|
||||
c->send_sighup = false;
|
||||
@ -23,11 +24,13 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
|
||||
fprintf(f,
|
||||
"%sKillMode: %s\n"
|
||||
"%sKillSignal: SIG%s\n"
|
||||
"%sRestartKillSignal: SIG%s\n"
|
||||
"%sFinalKillSignal: SIG%s\n"
|
||||
"%sSendSIGKILL: %s\n"
|
||||
"%sSendSIGHUP: %s\n",
|
||||
prefix, kill_mode_to_string(c->kill_mode),
|
||||
prefix, signal_to_string(c->kill_signal),
|
||||
prefix, signal_to_string(restart_kill_signal(c)),
|
||||
prefix, signal_to_string(c->final_kill_signal),
|
||||
prefix, yes_no(c->send_sigkill),
|
||||
prefix, yes_no(c->send_sighup));
|
||||
|
@ -21,6 +21,7 @@ typedef enum KillMode {
|
||||
struct KillContext {
|
||||
KillMode kill_mode;
|
||||
int kill_signal;
|
||||
int restart_kill_signal;
|
||||
int final_kill_signal;
|
||||
int watchdog_signal;
|
||||
bool send_sigkill;
|
||||
@ -47,3 +48,9 @@ KillMode kill_mode_from_string(const char *s) _pure_;
|
||||
|
||||
const char *kill_who_to_string(KillWho k) _const_;
|
||||
KillWho kill_who_from_string(const char *s) _pure_;
|
||||
|
||||
static inline int restart_kill_signal(const KillContext *c) {
|
||||
if (c->restart_kill_signal != 0)
|
||||
return c->restart_kill_signal;
|
||||
return c->kill_signal;
|
||||
}
|
||||
|
@ -161,6 +161,7 @@ m4_define(`KILL_CONTEXT_CONFIG_ITEMS',
|
||||
$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup)
|
||||
$1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode)
|
||||
$1.KillSignal, config_parse_signal, 0, offsetof($1, kill_context.kill_signal)
|
||||
$1.RestartKillSignal, config_parse_signal, 0, offsetof($1, kill_context.restart_kill_signal)
|
||||
$1.FinalKillSignal, config_parse_signal, 0, offsetof($1, kill_context.final_kill_signal)
|
||||
$1.WatchdogSignal, config_parse_signal, 0, offsetof($1, kill_context.watchdog_signal)'
|
||||
)m4_dnl
|
||||
|
@ -866,6 +866,8 @@ static int state_to_kill_operation(MountState state) {
|
||||
switch (state) {
|
||||
|
||||
case MOUNT_REMOUNTING_SIGTERM:
|
||||
return KILL_RESTART;
|
||||
|
||||
case MOUNT_UNMOUNTING_SIGTERM:
|
||||
return KILL_TERMINATE;
|
||||
|
||||
|
@ -1838,13 +1838,17 @@ fail:
|
||||
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(ServiceState state) {
|
||||
static int state_to_kill_operation(Service *s, ServiceState state) {
|
||||
switch (state) {
|
||||
|
||||
case SERVICE_STOP_WATCHDOG:
|
||||
return KILL_WATCHDOG;
|
||||
|
||||
case SERVICE_STOP_SIGTERM:
|
||||
if (unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
_fallthrough_;
|
||||
|
||||
case SERVICE_FINAL_SIGTERM:
|
||||
return KILL_TERMINATE;
|
||||
|
||||
@ -1875,7 +1879,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(state),
|
||||
state_to_kill_operation(s, state),
|
||||
s->main_pid,
|
||||
s->control_pid,
|
||||
s->main_pid_alien);
|
||||
|
@ -2077,6 +2077,16 @@ fail:
|
||||
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(Socket *s, SocketState state) {
|
||||
if (state == SOCKET_STOP_PRE_SIGTERM && unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
|
||||
if (state == SOCKET_FINAL_SIGTERM)
|
||||
return KILL_TERMINATE;
|
||||
|
||||
return KILL_KILL;
|
||||
}
|
||||
|
||||
static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
||||
int r;
|
||||
|
||||
@ -2088,8 +2098,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
!IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_FINAL_SIGTERM) ?
|
||||
KILL_KILL : KILL_TERMINATE,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
|
@ -712,21 +712,32 @@ static void swap_enter_dead_or_active(Swap *s, SwapResult f) {
|
||||
swap_enter_dead(s, f);
|
||||
}
|
||||
|
||||
static int state_to_kill_operation(Swap *s, SwapState state) {
|
||||
if (state == SWAP_DEACTIVATING_SIGTERM) {
|
||||
if (unit_has_job_type(UNIT(s), JOB_RESTART))
|
||||
return KILL_RESTART;
|
||||
else
|
||||
return KILL_TERMINATE;
|
||||
}
|
||||
|
||||
return KILL_KILL;
|
||||
}
|
||||
|
||||
static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
|
||||
int r;
|
||||
KillOperation kop;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->result == SWAP_SUCCESS)
|
||||
s->result = f;
|
||||
|
||||
if (state == SWAP_DEACTIVATING_SIGTERM)
|
||||
kop = KILL_TERMINATE;
|
||||
else
|
||||
kop = KILL_KILL;
|
||||
|
||||
r = unit_kill_context(UNIT(s), &s->kill_context, kop, -1, s->control_pid, false);
|
||||
r = unit_kill_context(UNIT(s),
|
||||
&s->kill_context,
|
||||
state_to_kill_operation(s, state),
|
||||
-1,
|
||||
s->control_pid,
|
||||
false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
@ -4695,6 +4695,9 @@ static int operation_to_signal(KillContext *c, KillOperation k) {
|
||||
case KILL_TERMINATE_AND_LOG:
|
||||
return c->kill_signal;
|
||||
|
||||
case KILL_RESTART:
|
||||
return restart_kill_signal(c);
|
||||
|
||||
case KILL_KILL:
|
||||
return c->final_kill_signal;
|
||||
|
||||
|
@ -18,6 +18,7 @@ typedef struct UnitRef UnitRef;
|
||||
typedef enum KillOperation {
|
||||
KILL_TERMINATE,
|
||||
KILL_TERMINATE_AND_LOG,
|
||||
KILL_RESTART,
|
||||
KILL_KILL,
|
||||
KILL_WATCHDOG,
|
||||
_KILL_OPERATION_MAX,
|
||||
|
@ -1355,15 +1355,12 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||
static int bus_append_kill_property(sd_bus_message *m, const char *field, const char *eq) {
|
||||
|
||||
if (streq(field, "KillMode"))
|
||||
|
||||
return bus_append_string(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "SendSIGHUP", "SendSIGKILL"))
|
||||
|
||||
return bus_append_parse_boolean(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "KillSignal", "FinalKillSignal", "WatchdogSignal"))
|
||||
|
||||
if (STR_IN_SET(field, "KillSignal", "RestartKillSignal", "FinalKillSignal", "WatchdogSignal"))
|
||||
return bus_append_signal_from_string(m, field, eq);
|
||||
|
||||
return 0;
|
||||
|
@ -19,6 +19,14 @@ systemd-run --unit=four -p Type=exec /bin/sleep infinity
|
||||
! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity
|
||||
! systemd-run --unit=six -p Type=exec /tmp/brokenbinary
|
||||
|
||||
systemd-run --unit=seven -p KillSignal=SIGTERM -p RestartKillSignal=SIGINT -p Type=exec /bin/sleep infinity
|
||||
# Both TERM and SIGINT happen to have the same number on all architectures
|
||||
test $(systemctl show --value -p KillSignal seven.service) -eq 15
|
||||
test $(systemctl show --value -p RestartKillSignal seven.service) -eq 2
|
||||
|
||||
systemctl restart seven.service
|
||||
systemctl stop seven.service
|
||||
|
||||
systemd-analyze log-level info
|
||||
|
||||
echo OK > /testok
|
||||
|
@ -185,6 +185,7 @@ RequiresMountsFor=
|
||||
Requisite=
|
||||
Restart=
|
||||
RestartForceExitStatus=
|
||||
RestartKillSignal=
|
||||
RestartPreventExitStatus=
|
||||
RestartSec=
|
||||
ReusePort=
|
||||
|
Loading…
Reference in New Issue
Block a user