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