]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: unify call we use to synthesize cgroup empty events when we stopped watching...
authorLennart Poettering <lennart@poettering.net>
Fri, 12 Jan 2018 12:06:48 +0000 (13:06 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Jan 2018 20:22:50 +0000 (21:22 +0100)
This code is very similar in scope and service units, let's unify it in
one function. This changes little for service units, but for scope units
makes sure we go through the cgroup queue, which is something we should
do anyway.

src/core/cgroup.c
src/core/cgroup.h
src/core/scope.c
src/core/service.c

index b3cd12000e0f5385b1fc28ae8fd82d41774c51a5..47a3b6d3a2ff0e3f9fd5b4b893f0420e50285430 100644 (file)
@@ -1827,6 +1827,31 @@ static int unit_watch_pids_in_path(Unit *u, const char *path) {
         return ret;
 }
 
+int unit_synthesize_cgroup_empty_event(Unit *u) {
+        int r;
+
+        assert(u);
+
+        /* Enqueue a synthetic cgroup empty event if this unit doesn't watch any PIDs anymore. This is compatibility
+         * support for non-unified systems where notifications aren't reliable, and hence need to take whatever we can
+         * get as notification source as soon as we stopped having any useful PIDs to watch for. */
+
+        if (!u->cgroup_path)
+                return -ENOENT;
+
+        r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
+        if (r < 0)
+                return r;
+        if (r > 0) /* On unified we have reliable notifications, and don't need this */
+                return 0;
+
+        if (!set_isempty(u->pids))
+                return 0;
+
+        unit_add_to_cgroup_empty_queue(u);
+        return 0;
+}
+
 int unit_watch_all_pids(Unit *u) {
         int r;
 
index 0c5bb4a2c8b9c2da2ec0aa58284131cbaa0c72a8..d5c0bd43116b402807535bed5db4fd089c7c6e17 100644 (file)
@@ -192,6 +192,8 @@ Unit* manager_get_unit_by_pid(Manager *m, pid_t pid);
 int unit_search_main_pid(Unit *u, pid_t *ret);
 int unit_watch_all_pids(Unit *u);
 
+int unit_synthesize_cgroup_empty_event(Unit *u);
+
 int unit_get_memory_current(Unit *u, uint64_t *ret);
 int unit_get_tasks_current(Unit *u, uint64_t *ret);
 int unit_get_cpu_usage(Unit *u, nsec_t *ret);
index 10454d56b04651e7fe45c71b3774ccae849388ff..468dd812175c62a14a809a1ce085bdf72f5d6205 100644 (file)
@@ -472,19 +472,16 @@ static void scope_notify_cgroup_empty_event(Unit *u) {
 
 static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
-        /* If we get a SIGCHLD event for one of the processes we were
-           interested in, then we look for others to watch, under the
-           assumption that we'll sooner or later get a SIGCHLD for
-           them, as the original process we watched was probably the
-           parent of them, and they are hence now our children. */
+        assert(u);
 
+        /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to
+         * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original
+         * process we watched was probably the parent of them, and they are hence now our children. */
         unit_tidy_watch_pids(u, 0, 0);
         unit_watch_all_pids(u);
 
-        /* If the PID set is empty now, then let's finish this off
-           (On unified we use proper notifications) */
-        if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) == 0 && set_isempty(u->pids))
-                scope_notify_cgroup_empty_event(u);
+        /* If the PID set is empty now, then let's finish this off. */
+        unit_synthesize_cgroup_empty_event(u);
 }
 
 static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
index 445f3ff60461b6b0d11319846ecc349e2daf5375..124b334e3e4b8eb3a7b936ac792b100736260880 100644 (file)
@@ -3301,18 +3301,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         if (notify_dbus)
                 unit_add_to_dbus_queue(u);
 
-        /* We got one SIGCHLD for the service, let's watch all
-         * processes that are now running of the service, and watch
-         * that. Among the PIDs we then watch will be children
-         * reassigned to us, which hopefully allows us to identify
-         * when all children are gone */
+        /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to watch,
+         * under the assumption that we'll sooner or later get a SIGCHLD for them, as the original process we watched
+         * was probably the parent of them, and they are hence now our children. */
         unit_tidy_watch_pids(u, s->main_pid, s->control_pid);
         unit_watch_all_pids(u);
 
-        /* If the PID set is empty now, then let's finish this off
-           (On unified we use proper notifications) */
-        if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) == 0 && set_isempty(u->pids))
-                unit_add_to_cgroup_empty_queue(u);
+        /* If the PID set is empty now, then let's check if the cgroup is empty too and finish off the unit. */
+        unit_synthesize_cgroup_empty_event(u);
 }
 
 static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {