Blob Blame History Raw
From 35bf3bd6a276fa58fa6ed5a258a7fbc4ba8bce05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Nykr=C3=BDn?= <lnykryn@redhat.com>
Date: Sat, 16 Jul 2016 21:04:13 +0200
Subject: [PATCH] manager: don't skip sigchld handler for main and control pid
 for services (#3738)

During stop when service has one "regular" pid one main pid and one
control pid and the sighld for the regular one is processed first the
unit_tidy_watch_pids will skip the main and control pid and does not
remove them from u->pids(). But then we skip the sigchld event because we
already did one in the iteration and there are two pids in u->pids.

v2: Use general unit_main_pid() and unit_control_pid() instead of
reaching directly to service structure.
Cherry-picked from: ccc2c98e1b0c06861577632440b996ca16cefd53
Resolves: #1342173
---
 src/core/busname.c | 10 ++++++++++
 src/core/manager.c |  5 ++++-
 src/core/mount.c   | 10 ++++++++++
 src/core/service.c | 19 +++++++++++++++++++
 src/core/socket.c  | 10 ++++++++++
 src/core/swap.c    | 10 ++++++++++
 src/core/unit.c    | 18 ++++++++++++++++++
 src/core/unit.h    |  9 +++++++++
 8 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/src/core/busname.c b/src/core/busname.c
index 43d7607..f626ba9 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -997,6 +997,14 @@ static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
 
+static int busname_control_pid(Unit *u) {
+        BusName *n = BUSNAME(u);
+
+        assert(n);
+
+        return n->control_pid;
+}
+
 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
         [BUSNAME_SUCCESS] = "success",
         [BUSNAME_FAILURE_RESOURCES] = "resources",
@@ -1047,6 +1055,8 @@ const UnitVTable busname_vtable = {
 
         .supported = busname_supported,
 
+        .control_pid = busname_control_pid,
+
         .bus_interface = "org.freedesktop.systemd1.BusName",
         .bus_vtable = bus_busname_vtable,
 
diff --git a/src/core/manager.c b/src/core/manager.c
index b63d929..87b5e57 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1756,7 +1756,10 @@ static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) {
         unit_unwatch_pid(u, si->si_pid);
 
         if (UNIT_VTABLE(u)->sigchld_event) {
-                if (set_size(u->pids) <= 1 || iteration != u->sigchldgen) {
+                if (set_size(u->pids) <= 1 ||
+                    iteration != u->sigchldgen ||
+                    unit_main_pid(u) == si->si_pid ||
+                    unit_control_pid(u) == si->si_pid) {
                         UNIT_VTABLE(u)->sigchld_event(u, si->si_pid, si->si_code, si->si_status);
                         u->sigchldgen = iteration;
                 } else
diff --git a/src/core/mount.c b/src/core/mount.c
index 23f63ce..4dc9f2e 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1883,6 +1883,14 @@ static const char* const mount_state_table[_MOUNT_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(mount_state, MountState);
 
+static int mount_control_pid(Unit *u) {
+        Mount *m = MOUNT(u);
+
+        assert(m);
+
+        return m->control_pid;
+}
+
 static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
         [MOUNT_EXEC_MOUNT] = "ExecMount",
         [MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
@@ -1944,6 +1952,8 @@ const UnitVTable mount_vtable = {
 
         .reset_failed = mount_reset_failed,
 
+        .control_pid = mount_control_pid,
+
         .bus_interface = "org.freedesktop.systemd1.Mount",
         .bus_vtable = bus_mount_vtable,
         .bus_set_property = bus_mount_set_property,
diff --git a/src/core/service.c b/src/core/service.c
index ae5e610..f102ef3 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3028,6 +3028,22 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(service_state, ServiceState);
 
+static int service_main_pid(Unit *u) {
+        Service *s = SERVICE(u);
+
+        assert(s);
+
+        return s->main_pid;
+}
+
+static int service_control_pid(Unit *u) {
+        Service *s = SERVICE(u);
+
+        assert(s);
+
+        return s->control_pid;
+}
+
 static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
         [SERVICE_RESTART_NO] = "no",
         [SERVICE_RESTART_ON_SUCCESS] = "on-success",
@@ -3138,6 +3154,9 @@ const UnitVTable service_vtable = {
         .notify_cgroup_empty = service_notify_cgroup_empty_event,
         .notify_message = service_notify_message,
 
+        .main_pid = service_main_pid,
+        .control_pid = service_control_pid,
+
         .bus_name_owner_change = service_bus_name_owner_change,
 
         .bus_interface = "org.freedesktop.systemd1.Service",
diff --git a/src/core/socket.c b/src/core/socket.c
index bc677a2..771af0d 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2648,6 +2648,14 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
 
+static int socket_control_pid(Unit *u) {
+        Socket *s = SOCKET(u);
+
+        assert(s);
+
+        return s->control_pid;
+}
+
 static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
         [SOCKET_EXEC_START_PRE] = "StartPre",
         [SOCKET_EXEC_START_CHOWN] = "StartChown",
@@ -2713,6 +2721,8 @@ const UnitVTable socket_vtable = {
 
         .reset_failed = socket_reset_failed,
 
+        .control_pid = socket_control_pid,
+
         .bus_interface = "org.freedesktop.systemd1.Socket",
         .bus_vtable = bus_socket_vtable,
         .bus_set_property = bus_socket_set_property,
diff --git a/src/core/swap.c b/src/core/swap.c
index 34a2c40..42f9959 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -1426,6 +1426,14 @@ static const char* const swap_state_table[_SWAP_STATE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(swap_state, SwapState);
 
+static int swap_control_pid(Unit *u) {
+        Swap *s = SWAP(u);
+
+        assert(s);
+
+        return s->control_pid;
+}
+
 static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
         [SWAP_EXEC_ACTIVATE] = "ExecActivate",
         [SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
@@ -1487,6 +1495,8 @@ const UnitVTable swap_vtable = {
 
         .reset_failed = swap_reset_failed,
 
+        .control_pid = swap_control_pid,
+
         .bus_interface = "org.freedesktop.systemd1.Swap",
         .bus_vtable = bus_swap_vtable,
         .bus_set_property = bus_swap_set_property,
diff --git a/src/core/unit.c b/src/core/unit.c
index 5b2becc..f03f185 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -3667,6 +3667,24 @@ int unit_setup_exec_runtime(Unit *u) {
         return exec_runtime_make(rt, unit_get_exec_context(u), u->id);
 }
 
+pid_t unit_control_pid(Unit *u) {
+        assert(u);
+
+        if (UNIT_VTABLE(u)->control_pid)
+                return UNIT_VTABLE(u)->control_pid(u);
+
+        return 0;
+}
+
+pid_t unit_main_pid(Unit *u) {
+        assert(u);
+
+        if (UNIT_VTABLE(u)->main_pid)
+                return UNIT_VTABLE(u)->main_pid(u);
+
+        return 0;
+}
+
 static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
         [UNIT_ACTIVE] = "active",
         [UNIT_RELOADING] = "reloading",
diff --git a/src/core/unit.h b/src/core/unit.h
index d936457..35287a5 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -399,6 +399,12 @@ struct UnitVTable {
 
         int (*get_timeout)(Unit *u, uint64_t *timeout);
 
+        /* Returns the main PID if there is any defined, or 0. */
+        pid_t (*main_pid)(Unit *u);
+
+        /* Returns the main PID if there is any defined, or 0. */
+        pid_t (*control_pid)(Unit *u);
+
         /* This is called for each unit type and should be used to
          * enumerate existing devices and load them. However,
          * everything that is loaded here should still stay in
@@ -610,6 +616,9 @@ int unit_make_transient(Unit *u);
 
 int unit_require_mounts_for(Unit *u, const char *path);
 
+pid_t unit_control_pid(Unit *u);
+pid_t unit_main_pid(Unit *u);
+
 const char *unit_active_state_to_string(UnitActiveState i) _const_;
 UnitActiveState unit_active_state_from_string(const char *s) _pure_;