X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=service.c;h=53d5505c2ea16b007607291f7e32faf54b3d8763;hp=a693c3339249ed6bd09d23988bdcba0ae433fc93;hb=0fd030bea1afa032d9afc791db4165a6848604b8;hpb=1d2d223c26a6bda2b3ffbce8140029c01e8296b7 diff --git a/service.c b/service.c index a693c3339..53d5505c2 100644 --- a/service.c +++ b/service.c @@ -370,7 +370,13 @@ static int service_load_sysv_path(Service *s, const char *path) { if (r == 0) continue; - r = unit_add_name(u, m); + if (unit_name_to_type(m) == UNIT_SERVICE) + r = unit_add_name(u, m); + else { + if ((r = unit_add_dependency_by_name_inverse(u, UNIT_REQUIRES, m)) >= 0) + r = unit_add_dependency_by_name(u, UNIT_BEFORE, m); + } + free(m); if (r < 0) @@ -475,6 +481,10 @@ static int service_load_sysv_path(Service *s, const char *path) { if ((r = sysv_exec_commands(s)) < 0) goto finish; + if ((r = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_SYSINIT_SERVICE)) < 0 || + (r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_SYSINIT_SERVICE)) < 0) + goto finish; + r = 1; finish: @@ -504,7 +514,7 @@ static int service_load_sysv_name(Service *s, const char *name) { r = service_load_sysv_path(s, path); free(path); - if (r >= 0) + if (r != 0) return r; } @@ -568,7 +578,7 @@ static int service_init(Unit *u) { return r; } - /* Load a classic init script as a fallback, if we couldn*t find anything */ + /* Load a classic init script as a fallback, if we couldn't find anything */ if (r == 0) if ((r = service_load_sysv(s)) <= 0) { service_done(u); @@ -581,6 +591,12 @@ static int service_init(Unit *u) { return r; } + /* Add default cgroup */ + if ((r = unit_add_default_cgroup(u)) < 0) { + service_done(u); + return r; + } + return 0; } @@ -599,10 +615,14 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sService State: %s\n" "%sPermissionsStartOnly: %s\n" - "%sRootDirectoryStartOnly: %s\n", + "%sRootDirectoryStartOnly: %s\n" + "%sValidNoProcess: %s\n" + "%sType: %s\n", prefix, service_state_to_string(s->state), prefix, yes_no(s->permissions_start_only), - prefix, yes_no(s->root_directory_start_only)); + prefix, yes_no(s->root_directory_start_only), + prefix, yes_no(s->valid_no_process), + prefix, service_type_to_string(s->type)); if (s->pid_file) fprintf(f, @@ -898,6 +918,7 @@ static int service_spawn( fds, n_fds, apply_permissions, apply_chroot, + UNIT(s)->meta.cgroup_bondings, &pid)) < 0) goto fail; @@ -1336,7 +1357,7 @@ static int main_pid_good(Service *s) { return s->main_pid > 0; /* We don't know the pid */ - return -1; + return -EAGAIN; } static bool control_pid_good(Service *s) { @@ -1345,6 +1366,15 @@ static bool control_pid_good(Service *s) { return s->control_pid > 0; } +static int cgroup_good(Service *s) { + assert(s); + + if (s->valid_no_process) + return -EAGAIN; + + return cgroup_bonding_is_empty_list(UNIT(s)->meta.cgroup_bondings); +} + static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { Service *s = SERVICE(u); bool success; @@ -1418,7 +1448,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { * don't care about failing commands. */ if (s->control_command->command_next && - (success || (s->state == SERVICE_EXEC_STOP || s->state == SERVICE_EXEC_STOP_POST))) + (success || (s->state == SERVICE_STOP || s->state == SERVICE_STOP_POST))) /* There is another command to * * execute, so let's do that. */ @@ -1477,7 +1507,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { case SERVICE_RELOAD: if (success) { - if (main_pid_good(s) != 0) + if (main_pid_good(s) != 0 && cgroup_good(s) != 0) service_set_state(s, SERVICE_RUNNING); else service_enter_stop(s, true); @@ -1580,6 +1610,33 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { } } +static void service_cgroup_notify_event(Unit *u) { + Service *s = SERVICE(u); + + assert(u); + + log_debug("%s: cgroup is empty", unit_id(u)); + + switch (s->state) { + + /* Waiting for SIGCHLD is usually more interesting, + * because it includes return codes/signals. Which is + * why we ignore the cgroup events for most cases, + * except when we don't know pid which to expect the + * SIGCHLD for. */ + + case SERVICE_RUNNING: + + if (!s->valid_no_process && main_pid_good(s) <= 0) + service_enter_stop(s, true); + + break; + + default: + ; + } +} + static int service_enumerate(Manager *m) { static const char * const rcnd[] = { @@ -1753,5 +1810,7 @@ const UnitVTable service_vtable = { .sigchld_event = service_sigchld_event, .timer_event = service_timer_event, + .cgroup_notify_empty = service_cgroup_notify_event, + .enumerate = service_enumerate };