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