static const char * const table[] = {
/* LSB defined facilities */
"local_fs", NULL,
- "network", SPECIAL_NETWORK_TARGET,
+ "network", SPECIAL_NETWORK_ONLINE_TARGET,
"named", SPECIAL_NSS_LOOKUP_TARGET,
"portmap", SPECIAL_RPCBIND_TARGET,
"remote_fs", SPECIAL_REMOTE_FS_TARGET,
FOREACH_WORD_QUOTED(w, z, strchr(t, ':')+1, i) {
char *n, *m;
+ bool is_before;
if (!(n = strndup(w, z))) {
r = -ENOMEM;
if (r == 0)
continue;
- r = unit_add_dependency_by_name(u, startswith_no_case(t, "X-Start-Before:") ? UNIT_BEFORE : UNIT_AFTER, m, NULL, true);
+ is_before = startswith_no_case(t, "X-Start-Before:");
+
+ if (streq(m, SPECIAL_NETWORK_ONLINE_TARGET) && !is_before)
+ /* the network-online target is special, as it needs to be actively pulled in */
+ r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, m, NULL, true);
+ else
+ r = unit_add_dependency_by_name(u, is_before ? UNIT_BEFORE : UNIT_AFTER, m, NULL, true);
if (r < 0)
log_error_unit(u->id, "[%s:%u] Failed to add dependency on %s, ignoring: %s",
return !r;
}
+static int service_execute_action(Service *s, FailureAction action, const char *reason, bool log_action_none);
+
static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
int r;
assert(s);
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
+ if (s->result != SERVICE_SUCCESS)
+ service_execute_action(s, s->failure_action, "failed", false);
+
if (allow_restart &&
!s->forbid_restart &&
(s->restart == SERVICE_RESTART_ALWAYS ||
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
-static int service_start_limit_test(Service *s) {
+static int service_execute_action(Service *s, FailureAction action, const char *reason, bool log_action_none) {
assert(s);
- if (ratelimit_test(&s->start_limit))
- return 0;
-
- if (s->start_limit_action == SERVICE_START_LIMIT_REBOOT ||
- s->start_limit_action == SERVICE_START_LIMIT_REBOOT_FORCE)
+ if (action == SERVICE_FAILURE_ACTION_REBOOT ||
+ action == SERVICE_FAILURE_ACTION_REBOOT_FORCE)
update_reboot_param_file(s->reboot_arg);
- switch (s->start_limit_action) {
+ switch (action) {
- case SERVICE_START_LIMIT_NONE:
- log_warning_unit(UNIT(s)->id,
- "%s start request repeated too quickly, refusing to start.",
- UNIT(s)->id);
+ case SERVICE_FAILURE_ACTION_NONE:
+ if (log_action_none)
+ log_warning_unit(UNIT(s)->id,
+ "%s %s, refusing to start.", UNIT(s)->id, reason);
break;
- case SERVICE_START_LIMIT_REBOOT: {
+ case SERVICE_FAILURE_ACTION_REBOOT: {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
log_warning_unit(UNIT(s)->id,
- "%s start request repeated too quickly, rebooting.", UNIT(s)->id);
+ "%s %s, rebooting.", UNIT(s)->id, reason);
r = manager_add_job_by_name(UNIT(s)->manager, JOB_START,
SPECIAL_REBOOT_TARGET, JOB_REPLACE,
break;
}
- case SERVICE_START_LIMIT_REBOOT_FORCE:
+ case SERVICE_FAILURE_ACTION_REBOOT_FORCE:
log_warning_unit(UNIT(s)->id,
- "%s start request repeated too quickly, forcibly rebooting.", UNIT(s)->id);
+ "%s %s, forcibly rebooting.", UNIT(s)->id, reason);
UNIT(s)->manager->exit_code = MANAGER_REBOOT;
break;
- case SERVICE_START_LIMIT_REBOOT_IMMEDIATE:
+ case SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE:
log_warning_unit(UNIT(s)->id,
- "%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id);
+ "%s %s, rebooting immediately.", UNIT(s)->id, reason);
sync();
if (s->reboot_arg) {
log_info("Rebooting with argument '%s'.", s->reboot_arg);
default:
log_error_unit(UNIT(s)->id,
- "start limit action=%i", s->start_limit_action);
- assert_not_reached("Unknown StartLimitAction.");
+ "failure action=%i", action);
+ assert_not_reached("Unknown FailureAction.");
}
return -ECANCELED;
}
+static int service_start_limit_test(Service *s) {
+ assert(s);
+
+ if (ratelimit_test(&s->start_limit))
+ return 0;
+
+ return service_execute_action(s, s->start_limit_action, "start request repeated too quickly", true);
+}
+
static int service_start(Unit *u) {
Service *s = SERVICE(u);
int r;
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
-static const char* const start_limit_action_table[_SERVICE_START_LIMIT_MAX] = {
- [SERVICE_START_LIMIT_NONE] = "none",
- [SERVICE_START_LIMIT_REBOOT] = "reboot",
- [SERVICE_START_LIMIT_REBOOT_FORCE] = "reboot-force",
- [SERVICE_START_LIMIT_REBOOT_IMMEDIATE] = "reboot-immediate"
+static const char* const failure_action_table[_SERVICE_FAILURE_ACTION_MAX] = {
+ [SERVICE_FAILURE_ACTION_NONE] = "none",
+ [SERVICE_FAILURE_ACTION_REBOOT] = "reboot",
+ [SERVICE_FAILURE_ACTION_REBOOT_FORCE] = "reboot-force",
+ [SERVICE_FAILURE_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate"
};
-DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
+DEFINE_STRING_TABLE_LOOKUP(failure_action, FailureAction);
const UnitVTable service_vtable = {
.object_size = sizeof(Service),