X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fservice.c;h=465e1a7a58ecc4bfb97519eec167c309f4d55ad4;hp=60576dfed77e3084eb65a59c7f1f00b4ac3cc93e;hb=85211309f0e14d7f804e1367e838291f39f6cec0;hpb=867b3b7d6b88ba4d07ec7c830576d4ac2f7dd226 diff --git a/src/service.c b/src/service.c index 60576dfed..465e1a7a5 100644 --- a/src/service.c +++ b/src/service.c @@ -118,8 +118,11 @@ static void service_init(Unit *u) { s->sysv_start_priority = -1; #endif s->socket_fd = -1; + s->guess_main_pid = true; exec_context_init(&s->exec_context); + s->exec_context.std_output = u->meta.manager->default_std_output; + s->exec_context.std_error = u->meta.manager->default_std_error; RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5); @@ -332,7 +335,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char /* Facilities starting with $ are most likely targets */ r = unit_name_build(n, NULL, ".target"); } else if (filename && streq(name, filename)) - /* Names equalling the file name of the services are redundant */ + /* Names equaling the file name of the services are redundant */ return 0; else /* Everything else we assume to be normal service names */ @@ -342,9 +345,7 @@ static int sysv_translate_facility(const char *name, const char *filename, char return -ENOMEM; finish: - - if (_r) - *_r = r; + *_r = r; return 1; } @@ -816,7 +817,7 @@ static int service_load_sysv_path(Service *s, const char *path) { s->restart = SERVICE_RESTART_NO; s->exec_context.std_output = (s->meta.manager->sysv_console || s->exec_context.std_input == EXEC_INPUT_TTY) - ? EXEC_OUTPUT_TTY : EXEC_OUTPUT_NULL; + ? EXEC_OUTPUT_TTY : s->meta.manager->default_std_output; s->exec_context.kill_mode = KILL_PROCESS_GROUP; /* We use the long description only if @@ -834,7 +835,7 @@ static int service_load_sysv_path(Service *s, const char *path) { if (description) { char *d; - if (!(d = strappend("LSB: ", description))) { + if (!(d = strappend(s->sysv_has_lsb ? "LSB: " : "SysV: ", description))) { r = -ENOMEM; goto finish; } @@ -1151,6 +1152,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { "%sPermissionsStartOnly: %s\n" "%sRootDirectoryStartOnly: %s\n" "%sRemainAfterExit: %s\n" + "%sGuessMainPID: %s\n" "%sType: %s\n" "%sRestart: %s\n" "%sNotifyAccess: %s\n", @@ -1158,6 +1160,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(s->permissions_start_only), prefix, yes_no(s->root_directory_start_only), prefix, yes_no(s->remain_after_exit), + prefix, yes_no(s->guess_main_pid), prefix, service_type_to_string(s->type), prefix, service_restart_to_string(s->restart), prefix, notify_access_to_string(s->notify_access)); @@ -1236,11 +1239,6 @@ static int service_load_pid_file(Service *s) { assert(s); - if (s->main_pid_known) - return 0; - - assert(s->main_pid <= 0); - if (!s->pid_file) return -ENOENT; @@ -1275,9 +1273,14 @@ static int service_search_main_pid(Service *s) { assert(s); + /* If we know it anyway, don't ever fallback to unreliable + * heuristics */ if (s->main_pid_known) return 0; + if (!s->guess_main_pid) + return 0; + assert(s->main_pid <= 0); if ((pid = cgroup_bonding_search_main_pid_list(s->meta.cgroup_bondings)) <= 0) @@ -1825,9 +1828,9 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) { int sig = (state == SERVICE_STOP_SIGTERM || state == SERVICE_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL; if (s->main_pid > 0) { - if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ? - -s->main_pid : - s->main_pid, sig) < 0 && errno != ESRCH) + if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ? + -s->main_pid : + s->main_pid, sig) < 0 && errno != ESRCH) log_warning("Failed to kill main process %li: %m", (long) s->main_pid); else @@ -1835,9 +1838,9 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) { } if (s->control_pid > 0) { - if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ? - -s->control_pid : - s->control_pid, sig) < 0 && errno != ESRCH) + if (kill_and_sigcont(s->exec_context.kill_mode == KILL_PROCESS_GROUP ? + -s->control_pid : + s->control_pid, sig) < 0 && errno != ESRCH) log_warning("Failed to kill control process %li: %m", (long) s->control_pid); else @@ -1860,7 +1863,7 @@ static void service_enter_signal(Service *s, ServiceState state, bool success) { if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0) goto fail; - if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) { + if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, pid_set)) < 0) { if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) log_warning("Failed to kill control group: %s", strerror(-r)); } else if (r > 0) @@ -2491,16 +2494,26 @@ static const char *service_sub_state_to_string(Unit *u) { return service_state_to_string(SERVICE(u)->state); } -#ifdef HAVE_SYSV_COMPAT static bool service_check_gc(Unit *u) { Service *s = SERVICE(u); assert(s); - return !!s->sysv_path; -} + /* Never clean up services that still have a process around, + * even if the service is formally dead. */ + if (cgroup_good(s) > 0 || + main_pid_good(s) > 0 || + control_pid_good(s) > 0) + return true; + +#ifdef HAVE_SYSV_COMPAT + if (s->sysv_path) + return true; #endif + return false; +} + static bool service_check_snapshot(Unit *u) { Service *s = SERVICE(u); @@ -2674,9 +2687,16 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { log_warning("%s: failed to load PID file %s: %s", s->meta.id, s->pid_file, strerror(-r)); } - /* Fall through */ + s->reload_failure = !success; + service_enter_running(s, true); + break; case SERVICE_RELOAD: + if (success) { + service_load_pid_file(s); + service_search_main_pid(s); + } + s->reload_failure = !success; service_enter_running(s, true); break; @@ -2755,7 +2775,7 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) { break; case SERVICE_STOP_SIGKILL: - /* Uh, wie sent a SIGKILL and it is still not gone? + /* Uh, we sent a SIGKILL and it is still not gone? * Must be something we cannot kill, so let's just be * weirded out and continue */ @@ -3030,7 +3050,7 @@ static int service_enumerate(Manager *m) { /* We honour K links only for halt/reboot. For the normal * runlevels we assume the stop jobs will be implicitly added - * by the core logic. Also, we don't really distuingish here + * by the core logic. Also, we don't really distinguish here * between the runlevels 0 and 6 and just add them to the * special shutdown target. On SUSE the boot.d/ runlevel is * also used for shutdown, so we add links for that too to the @@ -3208,7 +3228,7 @@ static int service_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusErro goto finish; } - if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0) + if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0) if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) r = q; } @@ -3305,9 +3325,7 @@ const UnitVTable service_vtable = { .active_state = service_active_state, .sub_state_to_string = service_sub_state_to_string, -#ifdef HAVE_SYSV_COMPAT .check_gc = service_check_gc, -#endif .check_snapshot = service_check_snapshot, .sigchld_event = service_sigchld_event,