]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add support for RestartKillSignal= to override signal used for restart jobs
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 1 Oct 2019 13:15:06 +0000 (15:15 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 2 Oct 2019 12:01:25 +0000 (14:01 +0200)
v2:
- if RestartKillSignal= is not specified, fall back to KillSignal=. This is necessary
  to preserve backwards compatibility (and keep KillSignal= generally useful).

15 files changed:
shell-completion/bash/systemd-run
shell-completion/zsh/_systemd-run
src/core/dbus-kill.c
src/core/kill.c
src/core/kill.h
src/core/load-fragment-gperf.gperf.m4
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/core/unit.c
src/core/unit.h
src/shared/bus-unit-util.c
test/TEST-23-TYPE-EXEC/testsuite.sh
test/fuzz/fuzz-unit-file/directives.service

index 4670973032b3d9d8844acdaa3eb1c5fafc23d5e3..707b038d9a8459431fd5388a8d2f29421e0895f3 100644 (file)
@@ -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=
index 6a703a075bf9510ec099019def1d0252b55580b3..ca0faa14844dd2e3fc1224992c921361a6626e81 100644 (file)
@@ -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= \
index e2b3a0d51750a5e233f3e2472e47f54013a1f445..30597e86f0d1dabb6c2087fb2dfa29deafd8463d 100644 (file)
@@ -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);
 
index e7608ac81feff1e4f7607609fce661355471233e..a9f468e29efaee3ff2a0e2cc3ee86b0c3485fa56 100644 (file)
@@ -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));
index 43648b6d8a2177c5016906839d52da8a31f56adb..1deb0aff9b6ed41fb07ba87ee37517ea4152b18d 100644 (file)
@@ -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;
+}
index 62dff99d86b607ca26a8c5ec2cffdb054709c9ac..d057c0d18b67b4d93ede581e0074cd952c9460fd 100644 (file)
@@ -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
index fb3467c3503c42f264f28a5ca1ba0488d94a547a..8a0c8be120e2ad7d05bac30348da81ccf7ddf881 100644 (file)
@@ -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;
 
index 8e313f8e902a91ccb897491938816d87e45d9d9a..1c677b4355604be3d4b2521ec0c11835145870a0 100644 (file)
@@ -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);
index d7ff7d1501a68faa44f2bd37277534af870eb596..7696490f8ac19ae7bf2c9e9521808343039cce9a 100644 (file)
@@ -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);
index 6d0cd517504f228cf0ad13579647971e5350ddf8..0924b35050e8981ac82703987bb76515cb612aa8 100644 (file)
@@ -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;
 
index 71fe7a6e2367486cbdce1b6b427c8f71c61c25fa..494185a046e26f99582dc486d03cde4b59766080 100644 (file)
@@ -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;
 
index 793ee638a6ace5697b6429d10efb66d79f39fee8..96f718acdcc638f4587faefd11f88d3a94c31361 100644 (file)
@@ -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,
index 2cd5adfd30c90575db957c2141adbd8b3bab4129..0b0772c9724ecbbce7043a9ffbbd73eaf8a65d44 100644 (file)
@@ -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;
index b161d97a7c5018c7cda33cc29155bc673fb59a10..50d6754b96b2550b4ae82fba963a25749560f45f 100755 (executable)
@@ -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
index fe9d451b41afdc19572cc6ed01eed74b3ede3b7e..068f4398b9bd6733336c32a7df1267cc564103e3 100644 (file)
@@ -185,6 +185,7 @@ RequiresMountsFor=
 Requisite=
 Restart=
 RestartForceExitStatus=
+RestartKillSignal=
 RestartPreventExitStatus=
 RestartSec=
 ReusePort=