diff options
Diffstat (limited to 'src/core/service.c')
-rw-r--r-- | src/core/service.c | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/src/core/service.c b/src/core/service.c index d72ff54daa..f7de5e89ff 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -142,8 +142,7 @@ static void service_unwatch_pid_file(Service *s) { log_unit_debug(UNIT(s), "Stopping watch for PID file %s", s->pid_file_pathspec->path); path_spec_unwatch(s->pid_file_pathspec); path_spec_done(s->pid_file_pathspec); - free(s->pid_file_pathspec); - s->pid_file_pathspec = NULL; + s->pid_file_pathspec = mfree(s->pid_file_pathspec); } static int service_set_main_pid(Service *s, pid_t pid) { @@ -287,14 +286,9 @@ static void service_done(Unit *u) { assert(s); - free(s->pid_file); - s->pid_file = NULL; - - free(s->status_text); - s->status_text = NULL; - - free(s->reboot_arg); - s->reboot_arg = NULL; + s->pid_file = mfree(s->pid_file); + s->status_text = mfree(s->status_text); + s->reboot_arg = mfree(s->reboot_arg); s->exec_runtime = exec_runtime_unref(s->exec_runtime); exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); @@ -313,8 +307,7 @@ static void service_done(Unit *u) { if (s->bus_name) { unit_unwatch_bus_name(u, s->bus_name); - free(s->bus_name); - s->bus_name = NULL; + s->bus_name = mfree(s->bus_name); } s->bus_endpoint_fd = safe_close(s->bus_endpoint_fd); @@ -401,7 +394,6 @@ static int service_add_fd_store_set(Service *s, FDSet *fds) { r = service_add_fd_store(s, fd); if (r < 0) return log_unit_error_errno(UNIT(s), r, "Couldn't add fd to fd store: %m"); - if (r > 0) { log_unit_debug(UNIT(s), "Added fd to fd store."); fd = -1; @@ -490,6 +482,12 @@ static int service_verify(Service *s) { return -EINVAL; } + if (s->usb_function_descriptors && !s->usb_function_strings) + log_unit_warning(UNIT(s), "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring."); + + if (!s->usb_function_descriptors && s->usb_function_strings) + log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring."); + return 0; } @@ -557,7 +555,7 @@ static int service_add_extras(Service *s) { if (r < 0) return r; - r = unit_add_default_slice(UNIT(s), &s->cgroup_context); + r = unit_set_default_slice(UNIT(s)); if (r < 0) return r; @@ -576,8 +574,10 @@ static int service_add_extras(Service *s) { return r; r = unit_watch_bus_name(UNIT(s), s->bus_name); + if (r == -EEXIST) + return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name); if (r < 0) - return r; + return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name); } if (UNIT(s)->default_dependencies) { @@ -701,13 +701,12 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%sStatus Text: %s\n", prefix, s->status_text); - if (s->n_fd_store_max > 0) { + if (s->n_fd_store_max > 0) fprintf(f, "%sFile Descriptor Store Max: %u\n" "%sFile Descriptor Store Current: %u\n", prefix, s->n_fd_store_max, prefix, s->n_fd_store); - } } static int service_load_pid_file(Service *s, bool may_warn) { @@ -766,7 +765,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { } static int service_search_main_pid(Service *s) { - pid_t pid; + pid_t pid = 0; int r; assert(s); @@ -781,9 +780,9 @@ static int service_search_main_pid(Service *s) { assert(s->main_pid <= 0); - pid = unit_search_main_pid(UNIT(s)); - if (pid <= 0) - return -ENOENT; + r = unit_search_main_pid(UNIT(s), &pid); + if (r < 0) + return r; log_unit_debug(UNIT(s), "Main PID guessed: "PID_FMT, pid); r = service_set_main_pid(s, pid); @@ -859,7 +858,7 @@ static void service_set_state(Service *s, ServiceState state) { /* For the inactive states unit_notify() will trim the cgroup, * but for exit we have to do that ourselves... */ if (state == SERVICE_EXITED && UNIT(s)->manager->n_reloading <= 0) - unit_destroy_cgroup_if_empty(UNIT(s)); + unit_prune_cgroup(UNIT(s)); /* For remain_after_exit services, let's see if we can "release" the * hold on the console, since unit_notify() only does that in case of @@ -1268,7 +1267,7 @@ static int cgroup_good(Service *s) { if (!UNIT(s)->cgroup_path) return 0; - r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path, true); + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path); if (r < 0) return r; @@ -1519,18 +1518,33 @@ fail: service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); } +static bool service_good(Service *s) { + int main_pid_ok; + assert(s); + + if (s->type == SERVICE_DBUS && !s->bus_name_good) + return false; + + main_pid_ok = main_pid_good(s); + if (main_pid_ok > 0) /* It's alive */ + return true; + if (main_pid_ok == 0) /* It's dead */ + return false; + + /* OK, we don't know anything about the main PID, maybe + * because there is none. Let's check the control group + * instead. */ + + return cgroup_good(s) != 0; +} + static void service_enter_running(Service *s, ServiceResult f) { - int main_pid_ok, cgroup_ok; assert(s); if (f != SERVICE_SUCCESS) s->result = f; - main_pid_ok = main_pid_good(s); - cgroup_ok = cgroup_good(s); - - if ((main_pid_ok > 0 || (main_pid_ok < 0 && cgroup_ok != 0)) && - (s->bus_name_good || s->type != SERVICE_DBUS)) { + if (service_good(s)) { /* If there are any queued up sd_notify() * notifications, process them now */ @@ -1923,8 +1937,7 @@ static int service_start(Unit *u) { s->forbid_restart = false; s->reset_cpu_usage = true; - free(s->status_text); - s->status_text = NULL; + s->status_text = mfree(s->status_text); s->status_errno = 0; s->notify_state = NOTIFY_UNKNOWN; @@ -1974,7 +1987,7 @@ static int service_reload(Unit *u) { assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED); service_enter_reload(s); - return 0; + return 1; } _pure_ static bool service_can_reload(Unit *u) { @@ -2628,7 +2641,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { break; } } else - service_search_main_pid(s); + (void) service_search_main_pid(s); service_enter_start_post(s); break; @@ -2650,7 +2663,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { break; } } else - service_search_main_pid(s); + (void) service_search_main_pid(s); service_enter_running(s, SERVICE_SUCCESS); break; @@ -2658,7 +2671,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { case SERVICE_RELOAD: if (f == SERVICE_SUCCESS) { service_load_pid_file(s, true); - service_search_main_pid(s); + (void) service_search_main_pid(s); } s->reload_result = f; @@ -2730,6 +2743,8 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us case SERVICE_RELOAD: log_unit_warning(UNIT(s), "Reload operation timed out. Stopping."); + service_unwatch_control_pid(s); + service_kill_control_processes(s); s->reload_result = SERVICE_FAILURE_TIMEOUT; service_enter_running(s, SERVICE_SUCCESS); break; @@ -2930,14 +2945,11 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds) } /* Interpret WATCHDOG= */ - if (strv_find(tags, "WATCHDOG=1")) { + if (strv_find(tags, "WATCHDOG=1")) service_reset_watchdog(s); - } - /* Add the passed fds to the fd store */ - if (strv_find(tags, "FDSTORE=1")) { + if (strv_find(tags, "FDSTORE=1")) service_add_fd_store_set(s, fds); - } /* Notify clients about changed status or main pid */ if (notify_dbus) @@ -3213,7 +3225,6 @@ const UnitVTable service_vtable = { .bus_name_owner_change = service_bus_name_owner_change, - .bus_interface = "org.freedesktop.systemd1.Service", .bus_vtable = bus_service_vtable, .bus_set_property = bus_service_set_property, .bus_commit_properties = bus_service_commit_properties, @@ -3229,13 +3240,10 @@ const UnitVTable service_vtable = { .finished_start_job = { [JOB_DONE] = "Started %s.", [JOB_FAILED] = "Failed to start %s.", - [JOB_DEPENDENCY] = "Dependency failed for %s.", - [JOB_TIMEOUT] = "Timed out starting %s.", }, .finished_stop_job = { [JOB_DONE] = "Stopped %s.", [JOB_FAILED] = "Stopped (with error) %s.", - [JOB_TIMEOUT] = "Timed out stopping %s.", }, }, }; |