Blame SOURCES/0233-core-only-watch-processes-when-it-s-really-necessary.patch

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