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.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
+6
-9
@@ -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) {
|
||||
|
||||
+5
-9
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user