]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: add a new D-Bus method for enquing POSIX signals with values to unit processes
authorLennart Poettering <lennart@poettering.net>
Wed, 15 Feb 2023 09:25:51 +0000 (10:25 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 17 Feb 2023 08:55:35 +0000 (09:55 +0100)
This augments the existing KillUnit() + Kill() methods with
QueueSignalUnit() + QueueSignal(), which are what sigqueue() is to
kill().

This is useful for sending our new SIGRTMIN+18 control signals to system
services.

13 files changed:
man/org.freedesktop.systemd1.xml
src/core/dbus-manager.c
src/core/dbus-unit.c
src/core/mount.c
src/core/org.freedesktop.systemd1.conf
src/core/scope.c
src/core/service.c
src/core/slice.c
src/core/socket.c
src/core/swap.c
src/core/unit.c
src/core/unit.h
src/test/test-execute.c

index 1592d046ad289e6985b3e1f301ff1b987e838351..5bae473856363e11d1d10bd261dd5ad835f8a71e 100644 (file)
@@ -112,6 +112,10 @@ node /org/freedesktop/systemd1 {
       KillUnit(in  s name,
                in  s whom,
                in  i signal);
+      QueueSignalUnit(in  s name,
+                      in  s whom,
+                      in  i signal,
+                      in  i value);
       CleanUnit(in  s name,
                 in  as mask);
       FreezeUnit(in  s name);
@@ -826,6 +830,8 @@ node /org/freedesktop/systemd1 {
 
     <variablelist class="dbus-method" generated="True" extra-ref="KillUnit()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="QueueSignalUnit()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="CleanUnit()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="FreezeUnit()"/>
@@ -1286,6 +1292,13 @@ node /org/freedesktop/systemd1 {
       <varname>ExecStop=</varname> and is spawned in parallel to the main daemon process in order to shut it
       down.</para>
 
+      <para><function>QueueSignalUnit()</function> is similar to <function>KillUnit()</function> but may be
+      used to enqueue a POSIX Realtime Signal (i.e. <constant>SIGRTMIN+…</constant> and
+      <constant>SIGRTMAX-…</constant>) to the selected process(es). Takes the same paramaters as
+      <function>KillUnit()</function> with one additional argument: an integer that is passed in the
+      <varname>sival_int</varname> value accompanying the queued signal. See <citerefentry project="man-pages"><refentrytitle>sigqueue</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+      details.</para>
+
       <para><function>GetJob()</function> returns the job object path for a specific job, identified by its
       id.</para>
 
@@ -1731,7 +1744,8 @@ node /org/freedesktop/systemd1 {
       <para>Read access is generally granted to all clients. Additionally, for unprivileged clients, some
       operations are allowed through the polkit privilege system. Operations which modify unit state
       (<function>StartUnit()</function>, <function>StopUnit()</function>, <function>KillUnit()</function>,
-      <function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
+      <function>QueueSignalUnit()</function>, <function>RestartUnit()</function> and similar,
+      <function>SetProperty()</function>) require
       <interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
       enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
       <function>EnableUnitFilesWithFlags()</function>, <function>DisableUnitFilesWithFlags()</function>,
@@ -1778,6 +1792,9 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
                  out a(uosos) affected_jobs);
       Kill(in  s whom,
            in  i signal);
+      QueueSignal(in  s whom,
+                  in  i signal,
+                  in  i value);
       ResetFailed();
       SetProperties(in  b runtime,
                     in  a(sv) properties);
@@ -2084,6 +2101,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-method" generated="True" extra-ref="Kill()"/>
 
+    <variablelist class="dbus-method" generated="True" extra-ref="QueueSignal()"/>
+
     <variablelist class="dbus-method" generated="True" extra-ref="ResetFailed()"/>
 
     <variablelist class="dbus-method" generated="True" extra-ref="SetProperties()"/>
@@ -2302,12 +2321,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       <para><function>Start()</function>, <function>Stop()</function>, <function>Reload()</function>,
       <function>Restart()</function>, <function>TryRestart()</function>,
       <function>ReloadOrRestart()</function>, <function>ReloadOrTryRestart()</function>,
-      <function>Kill()</function>, <function>ResetFailed()</function>, and
-      <function>SetProperties()</function> implement the same operation as the respective methods on the
+      <function>Kill()</function>, <function>QueueSignal()</function>, <function>ResetFailed()</function>,
+      and <function>SetProperties()</function> implement the same operation as the respective methods on the
       <interfacename>Manager</interfacename> object (see above). However, these methods operate on the unit
-      object and hence do not take a unit name parameter. Invoking the methods directly on the Manager
-      object has the advantage of not requiring a <function>GetUnit()</function> call to get the unit object
-      for a specific unit name. Calling the methods on the Manager object is hence a round trip
+      object and hence do not take a unit name parameter. Invoking the methods directly on the Manager object
+      has the advantage of not requiring a <function>GetUnit()</function> call to get the unit object for a
+      specific unit name. Calling the methods on the Manager object is hence a round trip
       optimization.</para>
     </refsect2>
 
index c4f205bc423f6d5de87baa58ad399fec7a7160ab..7d6f6bfc0fad5d6f423e1d1762f764d50a9007bc 100644 (file)
@@ -3034,6 +3034,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
                                 SD_BUS_NO_RESULT,
                                 method_kill_unit,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("QueueSignalUnit",
+                                SD_BUS_ARGS("s", name, "s", whom, "i", signal, "i", value),
+                                SD_BUS_NO_RESULT,
+                                method_kill_unit,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD_WITH_ARGS("CleanUnit",
                                 SD_BUS_ARGS("s", name, "as", mask),
                                 SD_BUS_NO_RESULT,
index 1ef98da6fd9f265fb0942d12534650b1ba95f952..8f851cbceb2ffad6287f5af68a4e008b0c5ddc1f 100644 (file)
@@ -513,10 +513,11 @@ int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_
 
 int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
         Unit *u = ASSERT_PTR(userdata);
+        int32_t value = 0;
         const char *swho;
         int32_t signo;
         KillWho who;
-        int r;
+        int r, code;
 
         assert(message);
 
@@ -528,17 +529,30 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
         if (r < 0)
                 return r;
 
+        if (startswith(sd_bus_message_get_member(message), "QueueSignal")) {
+                r = sd_bus_message_read(message, "i", &value);
+                if (r < 0)
+                        return r;
+
+                code = SI_QUEUE;
+        } else
+                code = SI_USER;
+
         if (isempty(swho))
                 who = KILL_ALL;
         else {
                 who = kill_who_from_string(swho);
                 if (who < 0)
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument: %s", swho);
         }
 
         if (!SIGNAL_VALID(signo))
                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
 
+        if (code == SI_QUEUE && !((signo >= SIGRTMIN) && (signo <= SIGRTMAX)))
+                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+                                         "Value parameter only accepted for realtime signals (SIGRTMIN…SIGRTMAX), refusing for signal SIG%s.", signal_to_string(signo));
+
         r = bus_verify_manage_units_async_full(
                         u,
                         "kill",
@@ -552,7 +566,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
         if (r == 0)
                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
 
-        r = unit_kill(u, who, signo, error);
+        r = unit_kill(u, who, signo, code, value, error);
         if (r < 0)
                 return r;
 
@@ -984,6 +998,11 @@ const sd_bus_vtable bus_unit_vtable[] = {
                                 SD_BUS_NO_RESULT,
                                 bus_unit_method_kill,
                                 SD_BUS_VTABLE_UNPRIVILEGED),
+        SD_BUS_METHOD_WITH_ARGS("QueueSignal",
+                                SD_BUS_ARGS("s", whom, "i", signal, "i", value),
+                                SD_BUS_NO_RESULT,
+                                bus_unit_method_kill,
+                                SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("ResetFailed",
                       NULL,
                       NULL,
index 993dce5118e53d7d18deabeed42e818d51372efb..95bd04f6e9f214bcc6e6a4b78698ebe5822ae570 100644 (file)
@@ -2158,12 +2158,12 @@ static void mount_reset_failed(Unit *u) {
         m->clean_result = MOUNT_SUCCESS;
 }
 
-static int mount_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
+static int mount_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
         Mount *m = MOUNT(u);
 
         assert(m);
 
-        return unit_kill_common(u, who, signo, -1, m->control_pid, error);
+        return unit_kill_common(u, who, signo, code, value, -1, m->control_pid, error);
 }
 
 static int mount_control_pid(Unit *u) {
index 1cef421db81037457bdf83d3546b6d41d803ce18..7f44c32b8395b36e06c4be9cb9c51961607a97d3 100644 (file)
                        send_interface="org.freedesktop.systemd1.Manager"
                        send_member="KillUnit"/>
 
+                <allow send_destination="org.freedesktop.systemd1"
+                       send_interface="org.freedesktop.systemd1.Manager"
+                       send_member="QueueSignalUnit"/>
+
                 <allow send_destination="org.freedesktop.systemd1"
                        send_interface="org.freedesktop.systemd1.Manager"
                        send_member="ResetFailedUnit"/>
                        send_interface="org.freedesktop.systemd1.Unit"
                        send_member="Kill"/>
 
+                <allow send_destination="org.freedesktop.systemd1"
+                       send_interface="org.freedesktop.systemd1.Unit"
+                       send_member="QueueSignal"/>
+
                 <allow send_destination="org.freedesktop.systemd1"
                        send_interface="org.freedesktop.systemd1.Unit"
                        send_member="ResetFailed"/>
index 914d1cc74467174c1db350d6d91da6d8cd3bffef..62f23a9e1ecf2d29f2b185bbc6f75009b427eca2 100644 (file)
@@ -530,8 +530,8 @@ static void scope_reset_failed(Unit *u) {
         s->result = SCOPE_SUCCESS;
 }
 
-static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
-        return unit_kill_common(u, who, signo, -1, -1, error);
+static int scope_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
+        return unit_kill_common(u, who, signo, code, value, -1, -1, error);
 }
 
 static int scope_get_timeout(Unit *u, usec_t *timeout) {
index 9ad3c3d99536f54d0bfc5fc2e6dfb4ff7d89e9ac..dc5ccfd239d1f2e0fd4922f0d4f43af93ffaaee0 100644 (file)
@@ -4596,12 +4596,12 @@ static void service_reset_failed(Unit *u) {
         s->flush_n_restarts = false;
 }
 
-static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
+static int service_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
         Service *s = SERVICE(u);
 
         assert(s);
 
-        return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
+        return unit_kill_common(u, who, signo, code, value, s->main_pid, s->control_pid, error);
 }
 
 static int service_main_pid(Unit *u) {
index 4824a300d0718c4c45e4aa82d0467ff8cb5407aa..eb0ba5e763d6db5c3b6352043ee335c080a9f9da 100644 (file)
@@ -247,8 +247,8 @@ static int slice_stop(Unit *u) {
         return 1;
 }
 
-static int slice_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
-        return unit_kill_common(u, who, signo, -1, -1, error);
+static int slice_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
+        return unit_kill_common(u, who, signo, code, value, -1, -1, error);
 }
 
 static int slice_serialize(Unit *u, FILE *f, FDSet *fds) {
index 409d415d8d99295a25164aa645110ebec6d29df8..8241ba050bfd9fe1c81fd4a6a1114eb1523b7530 100644 (file)
@@ -3299,8 +3299,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
                 socket_set_state(s, SOCKET_RUNNING);
 }
 
-static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
-        return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
+static int socket_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
+        return unit_kill_common(u, who, signo, code, value, -1, SOCKET(u)->control_pid, error);
 }
 
 static int socket_get_timeout(Unit *u, usec_t *timeout) {
index 2d25014e5f4abf2c5ff94765d474843da056518c..ab901a2cd171d4d959801f209e49c3775cb7a709 100644 (file)
@@ -1480,8 +1480,8 @@ static void swap_reset_failed(Unit *u) {
         s->clean_result = SWAP_SUCCESS;
 }
 
-static int swap_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
-        return unit_kill_common(u, who, signo, -1, SWAP(u)->control_pid, error);
+static int swap_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
+        return unit_kill_common(u, who, signo, code, value, -1, SWAP(u)->control_pid, error);
 }
 
 static int swap_get_timeout(Unit *u, usec_t *timeout) {
index 78a1f72f7fd05746957df0f56c35c7532b7c17f4..be7b19877f4678827f59aa0d0e7043b884406de1 100644 (file)
@@ -3785,15 +3785,16 @@ bool unit_will_restart(Unit *u) {
         return UNIT_VTABLE(u)->will_restart(u);
 }
 
-int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error) {
+int unit_kill(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error) {
         assert(u);
         assert(w >= 0 && w < _KILL_WHO_MAX);
         assert(SIGNAL_VALID(signo));
+        assert(IN_SET(code, SI_USER, SI_QUEUE));
 
         if (!UNIT_VTABLE(u)->kill)
                 return -EOPNOTSUPP;
 
-        return UNIT_VTABLE(u)->kill(u, w, signo, error);
+        return UNIT_VTABLE(u)->kill(u, w, signo, code, value, error);
 }
 
 void unit_notify_cgroup_oom(Unit *u, bool managed_oom) {
@@ -3838,21 +3839,48 @@ static int kill_common_log(pid_t pid, int signo, void *userdata) {
         return 1;
 }
 
+static int kill_or_sigqueue(pid_t pid, int signo, int code, int value) {
+        assert(pid > 0);
+        assert(SIGNAL_VALID(signo));
+
+        switch (code) {
+
+        case SI_USER:
+                log_debug("Killing " PID_FMT " with signal SIG%s.", pid, signal_to_string(signo));
+                return RET_NERRNO(kill(pid, signo));
+
+        case SI_QUEUE:
+                log_debug("Enqueuing value %i to " PID_FMT " on signal SIG%s.", value, pid, signal_to_string(signo));
+                return RET_NERRNO(sigqueue(pid, signo, (const union sigval) { .sival_int = value }));
+
+        default:
+                assert_not_reached();
+        }
+}
+
 int unit_kill_common(
                 Unit *u,
                 KillWho who,
                 int signo,
+                int code,
+                int value,
                 pid_t main_pid,
                 pid_t control_pid,
                 sd_bus_error *error) {
 
-        int r = 0;
         bool killed = false;
+        int ret = 0, r;
 
         /* This is the common implementation for explicit user-requested killing of unit processes, shared by
          * various unit types. Do not confuse with unit_kill_context(), which is what we use when we want to
          * stop a service ourselves. */
 
+        assert(u);
+        assert(who >= 0);
+        assert(who < _KILL_WHO_MAX);
+        assert(SIGNAL_VALID(signo));
+        assert(IN_SET(code, SI_USER, SI_QUEUE));
+
         if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL)) {
                 if (main_pid < 0)
                         return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type));
@@ -3867,71 +3895,85 @@ int unit_kill_common(
                         return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill");
         }
 
-        if (IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL))
-                if (control_pid > 0) {
-                        _cleanup_free_ char *comm = NULL;
-                        (void) get_process_comm(control_pid, &comm);
+        if (control_pid > 0 &&
+            IN_SET(who, KILL_CONTROL, KILL_CONTROL_FAIL, KILL_ALL, KILL_ALL_FAIL)) {
+                _cleanup_free_ char *comm = NULL;
+                (void) get_process_comm(control_pid, &comm);
 
-                        if (kill(control_pid, signo) < 0) {
-                                /* Report this failure both to the logs and to the client */
-                                sd_bus_error_set_errnof(
-                                                error, errno,
-                                                "Failed to send signal SIG%s to control process " PID_FMT " (%s): %m",
-                                                signal_to_string(signo), control_pid, strna(comm));
-                                r = log_unit_warning_errno(
-                                                u, errno,
-                                                "Failed to send signal SIG%s to control process " PID_FMT " (%s) on client request: %m",
-                                                signal_to_string(signo), control_pid, strna(comm));
-                        } else {
-                                log_unit_info(u, "Sent signal SIG%s to control process " PID_FMT " (%s) on client request.",
-                                              signal_to_string(signo), control_pid, strna(comm));
-                                killed = true;
-                        }
+                r = kill_or_sigqueue(control_pid, signo, code, value);
+                if (r < 0) {
+                        ret = r;
+
+                        /* Report this failure both to the logs and to the client */
+                        sd_bus_error_set_errnof(
+                                        error, r,
+                                        "Failed to send signal SIG%s to control process " PID_FMT " (%s): %m",
+                                        signal_to_string(signo), control_pid, strna(comm));
+                        log_unit_warning_errno(
+                                        u, r,
+                                        "Failed to send signal SIG%s to control process " PID_FMT " (%s) on client request: %m",
+                                        signal_to_string(signo), control_pid, strna(comm));
+                } else {
+                        log_unit_info(u, "Sent signal SIG%s to control process " PID_FMT " (%s) on client request.",
+                                      signal_to_string(signo), control_pid, strna(comm));
+                        killed = true;
                 }
+        }
 
-        if (IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL))
-                if (main_pid > 0) {
-                        _cleanup_free_ char *comm = NULL;
-                        (void) get_process_comm(main_pid, &comm);
+        if (main_pid > 0 &&
+            IN_SET(who, KILL_MAIN, KILL_MAIN_FAIL, KILL_ALL, KILL_ALL_FAIL)) {
 
-                        if (kill(main_pid, signo) < 0) {
-                                if (r == 0)
-                                        sd_bus_error_set_errnof(
-                                                        error, errno,
-                                                        "Failed to send signal SIG%s to main process " PID_FMT " (%s): %m",
-                                                        signal_to_string(signo), main_pid, strna(comm));
+                _cleanup_free_ char *comm = NULL;
+                (void) get_process_comm(main_pid, &comm);
+
+                r = kill_or_sigqueue(main_pid, signo, code, value);
+                if (r < 0) {
+                        if (ret == 0) {
+                                ret = r;
 
-                                r = log_unit_warning_errno(
-                                                u, errno,
-                                                "Failed to send signal SIG%s to main process " PID_FMT " (%s) on client request: %m",
+                                sd_bus_error_set_errnof(
+                                                error, r,
+                                                "Failed to send signal SIG%s to main process " PID_FMT " (%s): %m",
                                                 signal_to_string(signo), main_pid, strna(comm));
-                        } else {
-                                log_unit_info(u, "Sent signal SIG%s to main process " PID_FMT " (%s) on client request.",
-                                              signal_to_string(signo), main_pid, strna(comm));
-                                killed = true;
                         }
+
+                        log_unit_warning_errno(
+                                        u, r,
+                                        "Failed to send signal SIG%s to main process " PID_FMT " (%s) on client request: %m",
+                                        signal_to_string(signo), main_pid, strna(comm));
+
+                } else {
+                        log_unit_info(u, "Sent signal SIG%s to main process " PID_FMT " (%s) on client request.",
+                                      signal_to_string(signo), main_pid, strna(comm));
+                        killed = true;
                 }
+        }
 
-        if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path) {
+        /* Note: if we shall enqueue rather than kill we won't do this via the cgroup mechanism, since it
+         * doesn't really make much sense (and given that enqueued values are a relatively expensive
+         * resource, and we shouldn't allow us to be subjects for such allocation sprees) */
+        if (IN_SET(who, KILL_ALL, KILL_ALL_FAIL) && u->cgroup_path && code == SI_USER) {
                 _cleanup_set_free_ Set *pid_set = NULL;
-                int q;
 
                 /* Exclude the main/control pids from being killed via the cgroup */
                 pid_set = unit_pid_set(main_pid, control_pid);
                 if (!pid_set)
                         return log_oom();
 
-                q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, kill_common_log, u);
-                if (q < 0) {
-                        if (!IN_SET(q, -ESRCH, -ENOENT)) {
-                                if (r == 0)
+                r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, kill_common_log, u);
+                if (r < 0) {
+                        if (!IN_SET(r, -ESRCH, -ENOENT)) {
+                                if (ret == 0) {
+                                        ret = r;
+
                                         sd_bus_error_set_errnof(
-                                                        error, q,
+                                                        error, r,
                                                         "Failed to send signal SIG%s to auxiliary processes: %m",
                                                         signal_to_string(signo));
+                                }
 
-                                r = log_unit_warning_errno(
-                                                u, q,
+                                log_unit_warning_errno(
+                                                u, r,
                                                 "Failed to send signal SIG%s to auxiliary processes on client request: %m",
                                                 signal_to_string(signo));
                         }
@@ -3940,10 +3982,10 @@ int unit_kill_common(
         }
 
         /* If the "fail" versions of the operation are requested, then complain if the set of processes we killed is empty */
-        if (r == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_MAIN_FAIL))
+        if (ret == 0 && !killed && IN_SET(who, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_MAIN_FAIL))
                 return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No matching processes to kill");
 
-        return r;
+        return ret;
 }
 
 int unit_following_set(Unit *u, Set **s) {
index 58417ebd0ec080b8dbc43fee78d2cf878c905366..3f8377fbf64ebdc558dba196317a3e152cee7db9 100644 (file)
@@ -619,7 +619,7 @@ typedef struct UnitVTable {
         int (*stop)(Unit *u);
         int (*reload)(Unit *u);
 
-        int (*kill)(Unit *u, KillWho w, int signo, sd_bus_error *error);
+        int (*kill)(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
 
         /* Clear out the various runtime/state/cache/logs/configuration data */
         int (*clean)(Unit *u, ExecCleanMask m);
@@ -889,8 +889,8 @@ int unit_start(Unit *u, ActivationDetails *details);
 int unit_stop(Unit *u);
 int unit_reload(Unit *u);
 
-int unit_kill(Unit *u, KillWho w, int signo, sd_bus_error *error);
-int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
+int unit_kill(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
+int unit_kill_common(Unit *u, KillWho who, int signo, int code, int value, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
 
 void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
 
index f8c64b60426f14f1135727418710c27d92fbb065..f6d05afc1bd7dae7cb4f53ffc64520a2599049b6 100644 (file)
@@ -73,7 +73,7 @@ static void wait_for_service_finish(Manager *m, Unit *unit) {
                 n = now(CLOCK_MONOTONIC);
                 if (ts + timeout < n) {
                         log_error("Test timeout when testing %s", unit->id);
-                        r = unit_kill(unit, KILL_ALL, SIGKILL, NULL);
+                        r = unit_kill(unit, KILL_ALL, SIGKILL, SI_USER, 0, NULL);
                         if (r < 0)
                                 log_error_errno(r, "Failed to kill %s: %m", unit->id);
                         exit(EXIT_FAILURE);