static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata);
+static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
+
static void service_init(Unit *u) {
Service *s = SERVICE(u);
if (get_parent_of_pid(pid, &ppid) >= 0 && ppid != getpid()) {
log_warning_unit(UNIT(s)->id,
- "%s: Supervising process %lu which is not our child. We'll most likely not notice when it exits.",
- UNIT(s)->id, (unsigned long) pid);
+ "%s: Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.",
+ UNIT(s)->id, pid);
s->main_pid_alien = true;
} else
assert(s);
s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source);
- s->watchdog_timestamp = (struct dual_timestamp) { 0, 0 };
+ s->watchdog_timestamp = DUAL_TIMESTAMP_NULL;
}
-static void service_enter_signal(Service *s, ServiceState state, ServiceResult f);
-
-static void service_handle_watchdog(Service *s) {
- usec_t nw;
+static void service_start_watchdog(Service *s) {
int r;
assert(s);
- if (s->watchdog_usec == 0)
- return;
-
- nw = now(CLOCK_MONOTONIC);
- if (nw >= s->watchdog_timestamp.monotonic + s->watchdog_usec) {
- log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
- service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_WATCHDOG);
+ if (s->watchdog_usec <= 0)
return;
- }
if (s->watchdog_event_source) {
r = sd_event_source_set_time(s->watchdog_event_source, s->watchdog_timestamp.monotonic + s->watchdog_usec);
return;
}
- r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ON);
- } else
+ r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ONESHOT);
+ } else {
r = sd_event_add_monotonic(UNIT(s)->manager->event, s->watchdog_timestamp.monotonic + s->watchdog_usec, 0, service_dispatch_watchdog, s, &s->watchdog_event_source);
+ if (r < 0) {
+ log_warning_unit(UNIT(s)->id, "%s failed to add watchdog timer: %s", UNIT(s)->id, strerror(-r));
+ return;
+ }
+
+ /* Let's process everything else which might be a sign
+ * of living before we consider a service died. */
+ r = sd_event_source_set_priority(s->watchdog_event_source, SD_EVENT_PRIORITY_IDLE);
+ }
if (r < 0)
- log_warning_unit(UNIT(s)->id,
- "%s failed to install watchdog timer: %s",
- UNIT(s)->id, strerror(-r));
+ log_warning_unit(UNIT(s)->id, "%s failed to install watchdog timer: %s", UNIT(s)->id, strerror(-r));
}
static void service_reset_watchdog(Service *s) {
assert(s);
dual_timestamp_get(&s->watchdog_timestamp);
- service_handle_watchdog(s);
+ service_start_watchdog(s);
}
static void service_done(Unit *u) {
goto finish;
}
- r = sysv_translate_facility(n, path_get_file_name(path), &m);
+ r = sysv_translate_facility(n, basename(path), &m);
free(n);
if (r < 0)
goto finish;
}
- r = sysv_translate_facility(n, path_get_file_name(path), &m);
+ r = sysv_translate_facility(n, basename(path), &m);
if (r < 0) {
log_error_unit(u->id,
"[%s:%u] Failed to translate LSB dependency %s, ignoring: %s",
* majority of services. */
/* First, pull in base system */
- if (UNIT(s)->manager->running_as == SYSTEMD_SYSTEM) {
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_BASIC_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- } else if (UNIT(s)->manager->running_as == SYSTEMD_USER) {
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_SOCKETS_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_TIMERS_TARGET, NULL, true);
- if (r < 0)
- return r;
-
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_PATHS_TARGET, NULL, true);
- if (r < 0)
- return r;
- }
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES,
+ SPECIAL_BASIC_TARGET, NULL, true);
+ if (r < 0)
+ return r;
/* Second, activate normal shutdown */
r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS,
if (s->watchdog_usec > 0 && s->notify_access == NOTIFY_NONE)
s->notify_access = NOTIFY_MAIN;
- if (s->type == SERVICE_DBUS || s->bus_name) {
- r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES,
- SPECIAL_DBUS_SOCKET, NULL, true);
- if (r < 0)
- return r;
- }
-
if (UNIT(s)->default_dependencies) {
r = service_add_default_dependencies(s);
if (r < 0)
if (s->control_pid > 0)
fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) s->control_pid);
+ "%sControl PID: "PID_FMT"\n",
+ prefix, s->control_pid);
if (s->main_pid > 0)
fprintf(f,
- "%sMain PID: %lu\n"
+ "%sMain PID: "PID_FMT"\n"
"%sMain PID Known: %s\n"
"%sMain PID Alien: %s\n",
- prefix, (unsigned long) s->main_pid,
+ prefix, s->main_pid,
prefix, yes_no(s->main_pid_known),
prefix, yes_no(s->main_pid_alien));
if (kill(pid, 0) < 0 && errno != EPERM) {
if (may_warn)
log_info_unit(UNIT(s)->id,
- "PID %lu read from file %s does not exist.",
- (unsigned long) pid, s->pid_file);
+ "PID "PID_FMT" read from file %s does not exist.",
+ pid, s->pid_file);
return -ESRCH;
}
return 0;
log_debug_unit(UNIT(s)->id,
- "Main PID changing: %lu -> %lu",
- (unsigned long) s->main_pid, (unsigned long) pid);
+ "Main PID changing: "PID_FMT" -> "PID_FMT,
+ s->main_pid, pid);
service_unwatch_main_pid(s);
s->main_pid_known = false;
} else
log_debug_unit(UNIT(s)->id,
- "Main PID loaded: %lu", (unsigned long) pid);
+ "Main PID loaded: "PID_FMT, pid);
r = service_set_main_pid(s, pid);
if (r < 0)
if (r < 0) {
/* FIXME: we need to do something here */
log_warning_unit(UNIT(s)->id,
- "Failed to watch PID %lu from service %s",
- (unsigned long) pid, UNIT(s)->id);
+ "Failed to watch PID "PID_FMT" from service %s",
+ pid, UNIT(s)->id);
return r;
}
return -ENOENT;
log_debug_unit(UNIT(s)->id,
- "Main PID guessed: %lu", (unsigned long) pid);
+ "Main PID guessed: "PID_FMT, pid);
r = service_set_main_pid(s, pid);
if (r < 0)
return r;
if (r < 0)
/* FIXME: we need to do something here */
log_warning_unit(UNIT(s)->id,
- "Failed to watch PID %lu from service %s",
- (unsigned long) pid, UNIT(s)->id);
+ "Failed to watch PID "PID_FMT" from service %s",
+ pid, UNIT(s)->id);
return r;
return 0;
static void service_set_state(Service *s, ServiceState state) {
ServiceState old_state;
const UnitActiveState *table;
+
assert(s);
table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
service_unwatch_pid_file(s);
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL &&
- state != SERVICE_AUTO_RESTART)
+ if (!IN_SET(state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
+ SERVICE_AUTO_RESTART))
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- if (state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RUNNING &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL) {
+ if (!IN_SET(state,
+ SERVICE_START, SERVICE_START_POST,
+ SERVICE_RUNNING, SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
service_unwatch_main_pid(s);
s->main_command = NULL;
}
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL) {
+ if (!IN_SET(state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
service_unwatch_control_pid(s);
s->control_command = NULL;
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
}
- if (state != SERVICE_START_PRE &&
- state != SERVICE_START &&
- state != SERVICE_START_POST &&
- state != SERVICE_RUNNING &&
- state != SERVICE_RELOAD &&
- state != SERVICE_STOP &&
- state != SERVICE_STOP_SIGTERM &&
- state != SERVICE_STOP_SIGKILL &&
- state != SERVICE_STOP_POST &&
- state != SERVICE_FINAL_SIGTERM &&
- state != SERVICE_FINAL_SIGKILL &&
+ if (!IN_SET(state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RUNNING, SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
!(state == SERVICE_DEAD && UNIT(s)->job)) {
service_close_socket_fd(s);
service_connection_unref(s);
}
- if (state == SERVICE_STOP || state == SERVICE_STOP_SIGTERM)
+ if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
service_stop_watchdog(s);
/* For the inactive states unit_notify() will trim the cgroup,
}
if (old_state != state)
- log_debug_unit(UNIT(s)->id,
- "%s changed %s -> %s", UNIT(s)->id,
- service_state_to_string(old_state),
- service_state_to_string(state));
+ log_debug_unit(UNIT(s)->id, "%s changed %s -> %s", UNIT(s)->id, service_state_to_string(old_state), service_state_to_string(state));
unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
s->reload_result = SERVICE_SUCCESS;
if (s->deserialized_state != s->state) {
- if (s->deserialized_state == SERVICE_START_PRE ||
- s->deserialized_state == SERVICE_START ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL ||
- s->deserialized_state == SERVICE_STOP_POST ||
- s->deserialized_state == SERVICE_FINAL_SIGTERM ||
- s->deserialized_state == SERVICE_FINAL_SIGKILL) {
+ if (IN_SET(s->deserialized_state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
usec_t k;
- k = s->deserialized_state == SERVICE_START_PRE || s->deserialized_state == SERVICE_START ||
- s->deserialized_state == SERVICE_START_POST || s->deserialized_state == SERVICE_RELOAD ?
- s->timeout_start_usec : s->timeout_stop_usec;
+ k = IN_SET(s->deserialized_state, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD) ? s->timeout_start_usec : s->timeout_stop_usec;
/* For the start/stop timeouts 0 means off */
if (k > 0) {
return r;
}
- if ((s->deserialized_state == SERVICE_START &&
- (s->type == SERVICE_FORKING ||
- s->type == SERVICE_DBUS ||
- s->type == SERVICE_ONESHOT ||
- s->type == SERVICE_NOTIFY)) ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RUNNING ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL)
- if (s->main_pid > 0) {
- r = unit_watch_pid(UNIT(s), s->main_pid);
- if (r < 0)
- return r;
- }
+ if (pid_valid(s->main_pid) &&
+ ((s->deserialized_state == SERVICE_START && IN_SET(s->type, SERVICE_FORKING, SERVICE_DBUS, SERVICE_ONESHOT, SERVICE_NOTIFY)) ||
+ IN_SET(s->deserialized_state,
+ SERVICE_START, SERVICE_START_POST,
+ SERVICE_RUNNING, SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
+ r = unit_watch_pid(UNIT(s), s->main_pid);
+ if (r < 0)
+ return r;
+ }
- if (s->deserialized_state == SERVICE_START_PRE ||
- s->deserialized_state == SERVICE_START ||
- s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RELOAD ||
- s->deserialized_state == SERVICE_STOP ||
- s->deserialized_state == SERVICE_STOP_SIGTERM ||
- s->deserialized_state == SERVICE_STOP_SIGKILL ||
- s->deserialized_state == SERVICE_STOP_POST ||
- s->deserialized_state == SERVICE_FINAL_SIGTERM ||
- s->deserialized_state == SERVICE_FINAL_SIGKILL)
- if (s->control_pid > 0) {
- r = unit_watch_pid(UNIT(s), s->control_pid);
- if (r < 0)
- return r;
- }
+ if (pid_valid(s->control_pid) &&
+ IN_SET(s->deserialized_state,
+ SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
+ SERVICE_RELOAD,
+ SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
+ SERVICE_STOP_POST,
+ SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
+ r = unit_watch_pid(UNIT(s), s->control_pid);
+ if (r < 0)
+ return r;
+ }
- if (s->deserialized_state == SERVICE_START_POST ||
- s->deserialized_state == SERVICE_RUNNING)
- service_handle_watchdog(s);
+ if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
+ service_start_watchdog(s);
service_set_state(s, s->deserialized_state);
}
if (r < 0)
goto fail;
- our_env = new0(char*, 5);
+ our_env = new0(char*, 4);
if (!our_env) {
r = -ENOMEM;
goto fail;
}
if (s->main_pid > 0)
- if (asprintf(our_env + n_env++, "MAINPID=%lu", (unsigned long) s->main_pid) < 0) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (s->watchdog_usec > 0)
- if (asprintf(our_env + n_env++, "WATCHDOG_USEC=%llu", (unsigned long long) s->watchdog_usec) < 0) {
+ if (asprintf(our_env + n_env++, "MAINPID="PID_FMT, s->main_pid) < 0) {
r = -ENOMEM;
goto fail;
}
if (UNIT(s)->manager->running_as != SYSTEMD_SYSTEM)
- if (asprintf(our_env + n_env++, "MANAGERPID=%lu", (unsigned long) getpid()) < 0) {
+ if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT, getpid()) < 0) {
r = -ENOMEM;
goto fail;
}
UNIT(s)->manager->cgroup_supported,
path,
UNIT(s)->id,
+ s->watchdog_usec,
s->type == SERVICE_IDLE ? UNIT(s)->manager->idle_pipe : NULL,
s->exec_runtime,
&pid);
assert(s);
service_unwatch_control_pid(s);
-
- if (s->watchdog_usec > 0)
- service_reset_watchdog(s);
+ service_reset_watchdog(s);
s->control_command = s->exec_command[SERVICE_EXEC_START_POST];
if (s->control_command) {
unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result));
if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu",
- (unsigned long) s->control_pid);
+ unit_serialize_item_format(u, f, "control-pid", PID_FMT,
+ s->control_pid);
if (s->main_pid_known && s->main_pid > 0)
- unit_serialize_item_format(u, f, "main-pid", "%lu", (unsigned long) s->main_pid);
+ unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid);
unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known));
}
if (s->main_exec_status.pid > 0) {
- unit_serialize_item_format(u, f, "main-exec-status-pid", "%lu",
- (unsigned long) s->main_exec_status.pid);
+ unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT,
+ s->main_exec_status.pid);
dual_timestamp_serialize(f, "main-exec-status-start",
&s->main_exec_status.start_timestamp);
dual_timestamp_serialize(f, "main-exec-status-exit",
}
}
if (dual_timestamp_is_set(&s->watchdog_timestamp))
- dual_timestamp_serialize(f, "watchdog-timestamp",
- &s->watchdog_timestamp);
+ dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
if (s->forbid_restart)
unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart));
assert(s);
- return !s->got_socket_fd;
+ return (s->socket_fd < 0);
}
static int service_retry_pid_file(Service *s) {
/* If there is still a control process, wait for that first */
break;
+ case SERVICE_STOP_POST:
+ case SERVICE_FINAL_SIGTERM:
+ case SERVICE_FINAL_SIGKILL:
+
+ if (!control_pid_good(s))
+ service_enter_dead(s, f, true);
+ break;
+
default:
assert_not_reached("Uh, main process died at wrong time.");
}
case SERVICE_STOP_POST:
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
- service_enter_dead(s, f, true);
+ if (main_pid_good(s) <= 0)
+ service_enter_dead(s, f, true);
break;
default:
case SERVICE_START_PRE:
case SERVICE_START:
log_warning_unit(UNIT(s)->id,
- "%s operation timed out. Terminating.", UNIT(s)->id);
+ "%s %s operation timed out. Terminating.",
+ UNIT(s)->id,
+ s->state == SERVICE_START ? "start" : "start-pre");
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_START_POST:
log_warning_unit(UNIT(s)->id,
- "%s operation timed out. Stopping.", UNIT(s)->id);
+ "%s start-post operation timed out. Stopping.", UNIT(s)->id);
service_enter_stop(s, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_RELOAD:
log_warning_unit(UNIT(s)->id,
- "%s operation timed out. Stopping.", UNIT(s)->id);
+ "%s reload operation timed out. Stopping.", UNIT(s)->id);
s->reload_result = SERVICE_FAILURE_TIMEOUT;
service_enter_running(s, SERVICE_SUCCESS);
break;
case SERVICE_STOP_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(UNIT(s)->id,
- "%s stopping timed out. Killing.", UNIT(s)->id);
+ "%s stop-sigterm timed out. Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
log_warning_unit(UNIT(s)->id,
- "%s stopping timed out. Skipping SIGKILL.", UNIT(s)->id);
+ "%s stop-sigterm timed out. Skipping SIGKILL.", UNIT(s)->id);
service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT);
}
case SERVICE_STOP_POST:
log_warning_unit(UNIT(s)->id,
- "%s stopping timed out (2). Terminating.", UNIT(s)->id);
+ "%s stop-post timed out. Terminating.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT);
break;
case SERVICE_FINAL_SIGTERM:
if (s->kill_context.send_sigkill) {
log_warning_unit(UNIT(s)->id,
- "%s stopping timed out (2). Killing.", UNIT(s)->id);
+ "%s stop-final-sigterm timed out. Killing.", UNIT(s)->id);
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT);
} else {
log_warning_unit(UNIT(s)->id,
- "%s stopping timed out (2). Skipping SIGKILL. Entering failed mode.",
+ "%s stop-final-sigterm timed out. Skipping SIGKILL. Entering failed mode.",
UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false);
}
case SERVICE_FINAL_SIGKILL:
log_warning_unit(UNIT(s)->id,
- "%s still around after SIGKILL (2). Entering failed mode.", UNIT(s)->id);
+ "%s still around after final SIGKILL. Entering failed mode.", UNIT(s)->id);
service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true);
break;
assert(s);
assert(source == s->watchdog_event_source);
- service_handle_watchdog(s);
+ log_error_unit(UNIT(s)->id, "%s watchdog timeout!", UNIT(s)->id);
+ service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_WATCHDOG);
+
return 0;
}
break;
+ case SERVICE_STOP_POST:
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
if (main_pid_good(s) <= 0 && !control_pid_good(s))
static void service_notify_message(Unit *u, pid_t pid, char **tags) {
Service *s = SERVICE(u);
const char *e;
+ bool notify_dbus = false;
assert(u);
+ log_debug_unit(u->id, "%s: Got notification message from PID "PID_FMT" (%s...)",
+ u->id, pid, tags && *tags ? tags[0] : "(empty)");
+
if (s->notify_access == NOTIFY_NONE) {
log_warning_unit(u->id,
- "%s: Got notification message from PID %lu, but reception is disabled.",
- u->id, (unsigned long) pid);
+ "%s: Got notification message from PID "PID_FMT", but reception is disabled.",
+ u->id, pid);
return;
}
- if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) {
+ if (s->notify_access == NOTIFY_MAIN && s->main_pid != 0 && pid != s->main_pid) {
log_warning_unit(u->id,
- "%s: Got notification message from PID %lu, but reception only permitted for PID %lu",
- u->id, (unsigned long) pid, (unsigned long) s->main_pid);
+ "%s: Got notification message from PID "PID_FMT", but reception only permitted for PID "PID_FMT,
+ u->id, pid, s->main_pid);
return;
}
- log_debug_unit(u->id,
- "%s: Got message", u->id);
-
/* Interpret MAINPID= */
if ((e = strv_find_prefix(tags, "MAINPID=")) &&
(s->state == SERVICE_START ||
s->state == SERVICE_RELOAD)) {
if (parse_pid(e + 8, &pid) < 0)
- log_warning_unit(u->id,
- "Failed to parse notification message %s", e);
+ log_warning_unit(u->id, "Failed to parse notification message %s", e);
else {
- log_debug_unit(u->id,
- "%s: got %s", u->id, e);
+ log_debug_unit(u->id, "%s: got %s", u->id, e);
service_set_main_pid(s, pid);
unit_watch_pid(UNIT(s), pid);
+ notify_dbus = true;
}
}
/* Interpret READY= */
- if (s->type == SERVICE_NOTIFY &&
- s->state == SERVICE_START &&
- strv_find(tags, "READY=1")) {
- log_debug_unit(u->id,
- "%s: got READY=1", u->id);
-
+ if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START && strv_find(tags, "READY=1")) {
+ log_debug_unit(u->id, "%s: got READY=1", u->id);
service_enter_start_post(s);
+ notify_dbus = true;
}
/* Interpret STATUS= */
char *t;
if (e[7]) {
-
if (!utf8_is_valid(e+7)) {
- log_warning_unit(u->id,
- "Status message in notification is not UTF-8 clean.");
+ log_warning_unit(u->id, "Status message in notification is not UTF-8 clean.");
return;
}
+ log_debug_unit(u->id, "%s: got %s", u->id, e);
+
t = strdup(e+7);
if (!t) {
- log_error_unit(u->id,
- "Failed to allocate string.");
+ log_oom();
return;
}
- log_debug_unit(u->id,
- "%s: got %s", u->id, e);
+ } else
+ t = NULL;
+ if (!streq_ptr(s->status_text, t)) {
free(s->status_text);
s->status_text = t;
- } else {
- free(s->status_text);
- s->status_text = NULL;
- }
-
+ notify_dbus = true;
+ } else
+ free(t);
}
+
+ /* Interpet WATCHDOG= */
if (strv_find(tags, "WATCHDOG=1")) {
- log_debug_unit(u->id,
- "%s: got WATCHDOG=1", u->id);
- if (dual_timestamp_is_set(&s->watchdog_timestamp))
- service_reset_watchdog(s);
+ log_debug_unit(u->id, "%s: got WATCHDOG=1", u->id);
+ service_reset_watchdog(s);
}
/* Notify clients about changed status or main pid */
- unit_add_to_dbus_queue(u);
+ if (notify_dbus)
+ unit_add_to_dbus_queue(u);
}
#ifdef HAVE_SYSV_COMPAT
s->state == SERVICE_RUNNING ||
s->state == SERVICE_RELOAD)) {
+ _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
pid_t pid;
/* Try to acquire PID from bus service */
- r = sd_bus_get_owner_pid(u->manager->api_bus, name, &pid);
+ r = sd_bus_get_owner(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds);
+ if (r >= 0)
+ r = sd_bus_creds_get_pid(creds, &pid);
if (r >= 0) {
log_debug_unit(u->id, "%s's D-Bus name %s is now owned by process %u", u->id, name, (unsigned) pid);
}
int service_set_socket_fd(Service *s, int fd, Socket *sock) {
+ _cleanup_free_ char *peer = NULL;
+ int r;
assert(s);
assert(fd >= 0);
if (s->state != SERVICE_DEAD)
return -EAGAIN;
+ if (getpeername_pretty(fd, &peer) >= 0) {
+
+ if (UNIT(s)->description) {
+ _cleanup_free_ char *a;
+
+ a = strjoin(UNIT(s)->description, " (", peer, ")", NULL);
+ if (!a)
+ return -ENOMEM;
+
+ r = unit_set_description(UNIT(s), a);
+ } else
+ r = unit_set_description(UNIT(s), peer);
+
+ if (r < 0)
+ return r;
+ }
+
s->socket_fd = fd;
- s->got_socket_fd = true;
unit_ref_set(&s->accept_socket, UNIT(sock));
.bus_interface = "org.freedesktop.systemd1.Service",
.bus_vtable = bus_service_vtable,
- .bus_changing_properties = bus_service_changing_properties,
.bus_set_property = bus_service_set_property,
.bus_commit_properties = bus_service_commit_properties,