From: Lennart Poettering Date: Fri, 12 Jan 2018 12:06:48 +0000 (+0100) Subject: core: unify call we use to synthesize cgroup empty events when we stopped watching... X-Git-Tag: v237~37^2~4 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fsystemd.git;a=commitdiff_plain;h=11aef522c16d739653228ef3d5925b6fb25b9d8b core: unify call we use to synthesize cgroup empty events when we stopped watching any unit PIDs 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. --- diff --git a/src/core/cgroup.c b/src/core/cgroup.c index b3cd12000e0..47a3b6d3a2f 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 0c5bb4a2c8b..d5c0bd43116 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -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); diff --git a/src/core/scope.c b/src/core/scope.c index 10454d56b04..468dd812175 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -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) { diff --git a/src/core/service.c b/src/core/service.c index 445f3ff6046..124b334e3e4 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -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) {