From: Lennart Poettering Date: Wed, 27 Oct 2010 01:16:49 +0000 (+0200) Subject: service: when after startup only one process is in a service's cgroup, assume it... X-Git-Tag: v12~135 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=4fbf50b38e847aaa2932ac542e20c62f0c1605a3 service: when after startup only one process is in a service's cgroup, assume it is the main process --- diff --git a/TODO b/TODO index f41dd3c89..ecd5ff83f 100644 --- a/TODO +++ b/TODO @@ -66,8 +66,6 @@ * parse early boot time env var from dracut -* fix serialization of timers - * add switch to disable pull in retroactively * cryptsetup diff --git a/src/cgroup.c b/src/cgroup.c index d64ab63be..8b2ad5b0e 100644 --- a/src/cgroup.c +++ b/src/cgroup.c @@ -397,3 +397,54 @@ char *cgroup_bonding_to_string(CGroupBonding *b) { return r; } + +pid_t cgroup_bonding_search_main_pid(CGroupBonding *b) { + FILE *f; + pid_t pid = 0, npid; + int r; + + assert(b); + + if (!b->only_us) + return 0; + + if ((r = cg_enumerate_processes(b->controller, b->path, &f)) < 0) + return 0; + + while ((r = cg_read_pid(f, &npid)) > 0) { + + if (npid == pid) + continue; + + if (pid != 0) { + /* Dang, there's more than one PID in this + * group, so we don't know what process is the + * main process. */ + pid = 0; + break; + } + + pid = npid; + } + + fclose(f); + + return pid; +} + +pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *first) { + CGroupBonding *b; + pid_t pid; + + /* Try to find a main pid from this cgroup, but checking if + * there's only one PID in the cgroup and returning it. Later + * on we might want to add additional, smarter heuristics + * here. */ + + LIST_FOREACH(by_unit, b, first) + if ((pid = cgroup_bonding_search_main_pid(b)) != 0) + return pid; + + return 0; + +} diff --git a/src/cgroup.h b/src/cgroup.h index e38d7e79e..d6d5c86f1 100644 --- a/src/cgroup.h +++ b/src/cgroup.h @@ -71,6 +71,9 @@ CGroupBonding *cgroup_bonding_find_list(CGroupBonding *first, const char *contro char *cgroup_bonding_to_string(CGroupBonding *b); +pid_t cgroup_bonding_search_main_pid(CGroupBonding *b); +pid_t cgroup_bonding_search_main_pid_list(CGroupBonding *b); + #include "manager.h" int manager_setup_cgroup(Manager *m); diff --git a/src/service.c b/src/service.c index 46d7bbb1c..5cf78966a 100644 --- a/src/service.c +++ b/src/service.c @@ -1220,6 +1220,30 @@ static int service_load_pid_file(Service *s) { return 0; } +static int service_search_main_pid(Service *s) { + pid_t pid; + int r; + + assert(s); + + if (s->main_pid_known) + return 0; + + assert(s->main_pid <= 0); + + if ((pid = cgroup_bonding_search_main_pid_list(s->meta.cgroup_bondings)) <= 0) + return -ENOENT; + + if ((r = service_set_main_pid(s, pid)) < 0) + return r; + + if ((r = unit_watch_pid(UNIT(s), pid)) < 0) + /* FIXME: we need to do something here */ + return r; + + return 0; +} + static int service_get_sockets(Service *s, Set **_set) { Set *set; Iterator i; @@ -2595,8 +2619,8 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { * START_POST script */ if (success) { - if (s->pid_file) - service_load_pid_file(s); + service_load_pid_file(s); + service_search_main_pid(s); service_enter_start_post(s); } else diff --git a/src/systemctl.c b/src/systemctl.c index 9316ad073..d710bcf44 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -4047,7 +4047,7 @@ static int systemctl_help(void) { " pending\n" " -q --quiet Suppress output\n" " --no-block Do not wait until operation finished\n" - " --system Connect to system bus\n" + " --system Connect to system bus\n" " --session Connect to session bus\n" " --order When generating graph for dot, show only order\n" " --require When generating graph for dot, show only requirement\n"