Brian Stinson 2593d8
From 25b93538eba0275d35ef4b0792c2cd63d63d5e8d Mon Sep 17 00:00:00 2001
Brian Stinson 2593d8
From: Franck Bui <fbui@suse.com>
Brian Stinson 2593d8
Date: Tue, 19 Mar 2019 10:59:26 +0100
Brian Stinson 2593d8
Subject: [PATCH] core: only watch processes when it's really necessary
Brian Stinson 2593d8
MIME-Version: 1.0
Brian Stinson 2593d8
Content-Type: text/plain; charset=UTF-8
Brian Stinson 2593d8
Content-Transfer-Encoding: 8bit
Brian Stinson 2593d8
Brian Stinson 2593d8
If we know that main pid is our child then it's unnecessary to watch all
Brian Stinson 2593d8
other processes of a unit since in this case we will get SIGCHLD when the main
Brian Stinson 2593d8
process will exit and will act upon accordingly.
Brian Stinson 2593d8
Brian Stinson 2593d8
So let's watch all processes only if the main process is not our child since in
Brian Stinson 2593d8
this case we need to detect when the cgroup will become empty in order to
Brian Stinson 2593d8
figure out when the service becomes dead. This is only needed by cgroupv1.
Brian Stinson 2593d8
Brian Stinson 2593d8
Thanks Renaud Métrich for backporting this to RHEL.
Brian Stinson 2593d8
Resolves: #1744972
Brian Stinson 2593d8
---
Brian Stinson 2593d8
 src/core/service.c | 15 +++++++++------
Brian Stinson 2593d8
 1 file changed, 9 insertions(+), 6 deletions(-)
Brian Stinson 2593d8
Brian Stinson 2593d8
diff --git a/src/core/service.c b/src/core/service.c
Brian Stinson 2593d8
index 310838a5f6..b1ec52d220 100644
Brian Stinson 2593d8
--- a/src/core/service.c
Brian Stinson 2593d8
+++ b/src/core/service.c
Brian Stinson 2593d8
@@ -3410,8 +3410,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Brian Stinson 2593d8
                                 if (main_pid_good(s) <= 0)
Brian Stinson 2593d8
                                         service_enter_stop_post(s, f);
Brian Stinson 2593d8
 
Brian Stinson 2593d8
-                                /* If there is still a service
Brian Stinson 2593d8
-                                 * process around, wait until
Brian Stinson 2593d8
+                                /* If there is still a service process around, wait until
Brian Stinson 2593d8
                                  * that one quit, too */
Brian Stinson 2593d8
                                 break;
Brian Stinson 2593d8
 
Brian Stinson 2593d8
@@ -3433,10 +3432,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
Brian Stinson 2593d8
         if (notify_dbus)
Brian Stinson 2593d8
                 unit_add_to_dbus_queue(u);
Brian Stinson 2593d8
 
Brian Stinson 2593d8
-        /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to watch,
Brian Stinson 2593d8
-         * under the assumption that we'll sooner or later get a SIGCHLD for them, as the original process we watched
Brian Stinson 2593d8
-         * was probably the parent of them, and they are hence now our children. */
Brian Stinson 2593d8
-        (void) unit_enqueue_rewatch_pids(u);
Brian Stinson 2593d8
+        /* We watch the main/control process otherwise we can't retrieve the unit they
Brian Stinson 2593d8
+         * belong to with cgroupv1. But if they are not our direct child, we won't get a
Brian Stinson 2593d8
+         * SIGCHLD for them. Therefore we need to look for others to watch so we can
Brian Stinson 2593d8
+         * detect when the cgroup becomes empty. Note that the control process is always
Brian Stinson 2593d8
+         * our child so it's pointless to watch all other processes. */
Brian Stinson 2593d8
+        if (!control_pid_good(s))
Brian Stinson 2593d8
+                if (!s->main_pid_known || s->main_pid_alien)
Brian Stinson 2593d8
+                        (void) unit_enqueue_rewatch_pids(u);
Brian Stinson 2593d8
 }
Brian Stinson 2593d8
 
Brian Stinson 2593d8
 static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {