summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell-completion/bash/systemd-run2
-rw-r--r--shell-completion/zsh/_systemd-run2
-rw-r--r--src/core/dbus-kill.c22
-rw-r--r--src/core/kill.c3
-rw-r--r--src/core/kill.h7
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/mount.c2
-rw-r--r--src/core/service.c8
-rw-r--r--src/core/socket.c13
-rw-r--r--src/core/swap.c23
-rw-r--r--src/core/unit.c3
-rw-r--r--src/core/unit.h1
-rw-r--r--src/shared/bus-unit-util.c5
-rwxr-xr-xtest/TEST-23-TYPE-EXEC/testsuite.sh8
-rw-r--r--test/fuzz/fuzz-unit-file/directives.service1
15 files changed, 85 insertions, 16 deletions
diff --git a/shell-completion/bash/systemd-run b/shell-completion/bash/systemd-run
index 4670973032..707b038d9a 100644
--- a/shell-completion/bash/systemd-run
+++ b/shell-completion/bash/systemd-run
@@ -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=
diff --git a/shell-completion/zsh/_systemd-run b/shell-completion/zsh/_systemd-run
index 6a703a075b..ca0faa1484 100644
--- a/shell-completion/zsh/_systemd-run
+++ b/shell-completion/zsh/_systemd-run
@@ -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= \
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c
index e2b3a0d517..30597e86f0 100644
--- a/src/core/dbus-kill.c
+++ b/src/core/dbus-kill.c
@@ -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);
diff --git a/src/core/kill.c b/src/core/kill.c
index e7608ac81f..a9f468e29e 100644
--- a/src/core/kill.c
+++ b/src/core/kill.c
@@ -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));
diff --git a/src/core/kill.h b/src/core/kill.h
index 43648b6d8a..1deb0aff9b 100644
--- a/src/core/kill.h
+++ b/src/core/kill.h
@@ -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;
+}
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 62dff99d86..d057c0d18b 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -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
diff --git a/src/core/mount.c b/src/core/mount.c
index fb3467c350..8a0c8be120 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -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;
diff --git a/src/core/service.c b/src/core/service.c
index 8e313f8e90..1c677b4355 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -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);
diff --git a/src/core/socket.c b/src/core/socket.c
index d7ff7d1501..7696490f8a 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -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);
diff --git a/src/core/swap.c b/src/core/swap.c
index 6d0cd51750..0924b35050 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -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;
diff --git a/src/core/unit.c b/src/core/unit.c
index 71fe7a6e23..494185a046 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -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;
diff --git a/src/core/unit.h b/src/core/unit.h
index 793ee638a6..96f718acdc 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -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,
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 2cd5adfd30..0b0772c972 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -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;
diff --git a/test/TEST-23-TYPE-EXEC/testsuite.sh b/test/TEST-23-TYPE-EXEC/testsuite.sh
index b161d97a7c..50d6754b96 100755
--- a/test/TEST-23-TYPE-EXEC/testsuite.sh
+++ b/test/TEST-23-TYPE-EXEC/testsuite.sh
@@ -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
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
index fe9d451b41..068f4398b9 100644
--- a/test/fuzz/fuzz-unit-file/directives.service
+++ b/test/fuzz/fuzz-unit-file/directives.service
@@ -185,6 +185,7 @@ RequiresMountsFor=
Requisite=
Restart=
RestartForceExitStatus=
+RestartKillSignal=
RestartPreventExitStatus=
RestartSec=
ReusePort=