803fb7
From fd8580a8f42b1e10d75f43229b203fb889260b71 Mon Sep 17 00:00:00 2001
803fb7
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
803fb7
Date: Sat, 16 Jul 2016 21:04:13 +0200
803fb7
Subject: [PATCH] manager: don't skip sigchld handler for main and control pid
803fb7
 for services (#3738)
803fb7
803fb7
During stop when service has one "regular" pid one main pid and one
803fb7
control pid and the sighld for the regular one is processed first the
803fb7
unit_tidy_watch_pids will skip the main and control pid and does not
803fb7
remove them from u->pids(). But then we skip the sigchld event because we
803fb7
already did one in the iteration and there are two pids in u->pids.
803fb7
803fb7
v2: Use general unit_main_pid() and unit_control_pid() instead of
803fb7
reaching directly to service structure.
803fb7
Cherry-picked from: ccc2c98e1b0c06861577632440b996ca16cefd53
803fb7
Resolves: #1342173
803fb7
---
803fb7
 src/core/busname.c | 10 ++++++++++
803fb7
 src/core/manager.c |  5 ++++-
803fb7
 src/core/mount.c   | 10 ++++++++++
803fb7
 src/core/service.c | 19 +++++++++++++++++++
803fb7
 src/core/socket.c  | 10 ++++++++++
803fb7
 src/core/swap.c    | 10 ++++++++++
803fb7
 src/core/unit.c    | 18 ++++++++++++++++++
803fb7
 src/core/unit.h    |  9 +++++++++
803fb7
 8 files changed, 90 insertions(+), 1 deletion(-)
803fb7
803fb7
diff --git a/src/core/busname.c b/src/core/busname.c
803fb7
index 43d7607a3..f626ba96d 100644
803fb7
--- a/src/core/busname.c
803fb7
+++ b/src/core/busname.c
803fb7
@@ -997,6 +997,14 @@ static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
803fb7
 
803fb7
 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
803fb7
 
803fb7
+static int busname_control_pid(Unit *u) {
803fb7
+        BusName *n = BUSNAME(u);
803fb7
+
803fb7
+        assert(n);
803fb7
+
803fb7
+        return n->control_pid;
803fb7
+}
803fb7
+
803fb7
 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
803fb7
         [BUSNAME_SUCCESS] = "success",
803fb7
         [BUSNAME_FAILURE_RESOURCES] = "resources",
803fb7
@@ -1047,6 +1055,8 @@ const UnitVTable busname_vtable = {
803fb7
 
803fb7
         .supported = busname_supported,
803fb7
 
803fb7
+        .control_pid = busname_control_pid,
803fb7
+
803fb7
         .bus_interface = "org.freedesktop.systemd1.BusName",
803fb7
         .bus_vtable = bus_busname_vtable,
803fb7
 
803fb7
diff --git a/src/core/manager.c b/src/core/manager.c
803fb7
index d168777d2..5da836593 100644
803fb7
--- a/src/core/manager.c
803fb7
+++ b/src/core/manager.c
803fb7
@@ -1760,7 +1760,10 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
803fb7
         unit_unwatch_pid(u, si->si_pid);
803fb7
 
803fb7
         if (UNIT_VTABLE(u)->sigchld_event) {
803fb7
-                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
803fb7
+                if (set_size(u->pids) <= 1 ||
803fb7
+                    iteration != u->sigchldgen ||
803fb7
+                    unit_main_pid(u) == si->si_pid ||
803fb7
+                    unit_control_pid(u) == si->si_pid) {
803fb7
                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
803fb7
                         u->sigchldgen = iteration;
803fb7
                 } else
803fb7
diff --git a/src/core/mount.c b/src/core/mount.c
803fb7
index fe967bc03..3fbdb7daf 100644
803fb7
--- a/src/core/mount.c
803fb7
+++ b/src/core/mount.c
803fb7
@@ -1877,6 +1877,14 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
803fb7
 
803fb7
 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
803fb7
 
803fb7
+static int mount_control_pid(Unit *u) {
803fb7
+        Mount *m = MOUNT(u);
803fb7
+
803fb7
+        assert(m);
803fb7
+
803fb7
+        return m->control_pid;
803fb7
+}
803fb7
+
803fb7
 static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
803fb7
         [MOUNT_EXEC_MOUNT] = "ExecMount",
803fb7
         [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
803fb7
@@ -1938,6 +1946,8 @@ const UnitVTable mount_vtable = {
803fb7
 
803fb7
         .reset_failed = mount_reset_failed,
803fb7
 
803fb7
+        .control_pid = mount_control_pid,
803fb7
+
803fb7
         .bus_interface = "org.freedesktop.systemd1.Mount",
803fb7
         .bus_vtable = bus_mount_vtable,
803fb7
         .bus_set_property = bus_mount_set_property,
803fb7
diff --git a/src/core/service.c b/src/core/service.c
803fb7
index c76713b1c..babd3c52a 100644
803fb7
--- a/src/core/service.c
803fb7
+++ b/src/core/service.c
803fb7
@@ -3068,6 +3068,22 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
803fb7
 
803fb7
 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
803fb7
 
803fb7
+static int service_main_pid(Unit *u) {
803fb7
+        Service *s = SERVICE(u);
803fb7
+
803fb7
+        assert(s);
803fb7
+
803fb7
+        return s->main_pid;
803fb7
+}
803fb7
+
803fb7
+static int service_control_pid(Unit *u) {
803fb7
+        Service *s = SERVICE(u);
803fb7
+
803fb7
+        assert(s);
803fb7
+
803fb7
+        return s->control_pid;
803fb7
+}
803fb7
+
803fb7
 static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
803fb7
         [SERVICE_RESTART_NO] = "no",
803fb7
         [SERVICE_RESTART_ON_SUCCESS] = "on-success",
803fb7
@@ -3178,6 +3194,9 @@ const UnitVTable service_vtable = {
803fb7
         .notify_cgroup_empty = service_notify_cgroup_empty_event,
803fb7
         .notify_message = service_notify_message,
803fb7
 
803fb7
+        .main_pid = service_main_pid,
803fb7
+        .control_pid = service_control_pid,
803fb7
+
803fb7
         .bus_name_owner_change = service_bus_name_owner_change,
803fb7
 
803fb7
         .bus_interface = "org.freedesktop.systemd1.Service",
803fb7
diff --git a/src/core/socket.c b/src/core/socket.c
803fb7
index bc677a20f..771af0d24 100644
803fb7
--- a/src/core/socket.c
803fb7
+++ b/src/core/socket.c
803fb7
@@ -2648,6 +2648,14 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
803fb7
 
803fb7
 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
803fb7
 
803fb7
+static int socket_control_pid(Unit *u) {
803fb7
+        Socket *s = SOCKET(u);
803fb7
+
803fb7
+        assert(s);
803fb7
+
803fb7
+        return s->control_pid;
803fb7
+}
803fb7
+
803fb7
 static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
803fb7
         [SOCKET_EXEC_START_PRE] = "StartPre",
803fb7
         [SOCKET_EXEC_START_CHOWN] = "StartChown",
803fb7
@@ -2713,6 +2721,8 @@ const UnitVTable socket_vtable = {
803fb7
 
803fb7
         .reset_failed = socket_reset_failed,
803fb7
 
803fb7
+        .control_pid = socket_control_pid,
803fb7
+
803fb7
         .bus_interface = "org.freedesktop.systemd1.Socket",
803fb7
         .bus_vtable = bus_socket_vtable,
803fb7
         .bus_set_property = bus_socket_set_property,
803fb7
diff --git a/src/core/swap.c b/src/core/swap.c
803fb7
index 34a2c406d..42f995990 100644
803fb7
--- a/src/core/swap.c
803fb7
+++ b/src/core/swap.c
803fb7
@@ -1426,6 +1426,14 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
803fb7
 
803fb7
 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
803fb7
 
803fb7
+static int swap_control_pid(Unit *u) {
803fb7
+        Swap *s = SWAP(u);
803fb7
+
803fb7
+        assert(s);
803fb7
+
803fb7
+        return s->control_pid;
803fb7
+}
803fb7
+
803fb7
 static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
803fb7
         [SWAP_EXEC_ACTIVATE] = "ExecActivate",
803fb7
         [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
803fb7
@@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = {
803fb7
 
803fb7
         .reset_failed = swap_reset_failed,
803fb7
 
803fb7
+        .control_pid = swap_control_pid,
803fb7
+
803fb7
         .bus_interface = "org.freedesktop.systemd1.Swap",
803fb7
         .bus_vtable = bus_swap_vtable,
803fb7
         .bus_set_property = bus_swap_set_property,
803fb7
diff --git a/src/core/unit.c b/src/core/unit.c
803fb7
index d62135d87..0e90d130a 100644
803fb7
--- a/src/core/unit.c
803fb7
+++ b/src/core/unit.c
803fb7
@@ -3674,6 +3674,24 @@ int unit_setup_exec_runtime(Unit *u) {
803fb7
         return exec_runtime_make(rt, unit_get_exec_context(u), u->id);
803fb7
 }
803fb7
 
803fb7
+pid_t unit_control_pid(Unit *u) {
803fb7
+        assert(u);
803fb7
+
803fb7
+        if (UNIT_VTABLE(u)->control_pid)
803fb7
+                return UNIT_VTABLE(u)->control_pid(u);
803fb7
+
803fb7
+        return 0;
803fb7
+}
803fb7
+
803fb7
+pid_t unit_main_pid(Unit *u) {
803fb7
+        assert(u);
803fb7
+
803fb7
+        if (UNIT_VTABLE(u)->main_pid)
803fb7
+                return UNIT_VTABLE(u)->main_pid(u);
803fb7
+
803fb7
+        return 0;
803fb7
+}
803fb7
+
803fb7
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
803fb7
         [UNIT_ACTIVE] = "active",
803fb7
         [UNIT_RELOADING] = "reloading",
803fb7
diff --git a/src/core/unit.h b/src/core/unit.h
803fb7
index d93645777..35287a5b7 100644
803fb7
--- a/src/core/unit.h
803fb7
+++ b/src/core/unit.h
803fb7
@@ -399,6 +399,12 @@ struct UnitVTable {
803fb7
 
803fb7
         int (*get_timeout)(Unit *u, uint64_t *timeout);
803fb7
 
803fb7
+        /* Returns the main PID if there is any defined, or 0. */
803fb7
+        pid_t (*main_pid)(Unit *u);
803fb7
+
803fb7
+        /* Returns the main PID if there is any defined, or 0. */
803fb7
+        pid_t (*control_pid)(Unit *u);
803fb7
+
803fb7
         /* This is called for each unit type and should be used to
803fb7
          * enumerate existing devices and load them. However,
803fb7
          * everything that is loaded here should still stay in
803fb7
@@ -610,6 +616,9 @@ int unit_make_transient(Unit *u);
803fb7
 
803fb7
 int unit_require_mounts_for(Unit *u, const char *path);
803fb7
 
803fb7
+pid_t unit_control_pid(Unit *u);
803fb7
+pid_t unit_main_pid(Unit *u);
803fb7
+
803fb7
 const char *unit_active_state_to_string(UnitActiveState i) _const_;
803fb7
 UnitActiveState unit_active_state_from_string(const char *s) _pure_;
803fb7