assert(u);
assert(u->load_state == UNIT_STUB);
- s->timeout_usec = DEFAULT_TIMEOUT_USEC;
+ s->timeout_start_usec = DEFAULT_TIMEOUT_USEC;
+ s->timeout_stop_usec = DEFAULT_TIMEOUT_USEC;
s->restart_usec = DEFAULT_RESTART_USEC;
s->type = _SERVICE_TYPE_INVALID;
s->control_command = NULL;
s->main_command = NULL;
+ set_free(s->restart_ignore_status.code);
+ s->restart_ignore_status.code = NULL;
+ set_free(s->restart_ignore_status.signal);
+ s->restart_ignore_status.signal = NULL;
+
+ set_free(s->success_status.code);
+ s->success_status.code = NULL;
+ set_free(s->success_status.signal);
+ s->success_status.signal = NULL;
+
/* This will leak a process, but at least no memory or any of
* our resources */
service_unwatch_main_pid(s);
UNIT(s)->default_dependencies = false;
/* Don't timeout special services during boot (like fsck) */
- s->timeout_usec = 0;
- } else
- s->timeout_usec = DEFAULT_SYSV_TIMEOUT_USEC;
+ s->timeout_start_usec = 0;
+ s->timeout_stop_usec = 0;
+ } else {
+ s->timeout_start_usec = DEFAULT_SYSV_TIMEOUT_USEC;
+ s->timeout_stop_usec = DEFAULT_SYSV_TIMEOUT_USEC;
+ }
+
/* Special setting for all SysV services */
s->type = SERVICE_FORKING;
if (s->type == _SERVICE_TYPE_INVALID)
s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
- /* Oneshot services have disabled timeout by default */
- if (s->type == SERVICE_ONESHOT && !s->timeout_defined)
- s->timeout_usec = 0;
+ /* Oneshot services have disabled start timeout by default */
+ if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined)
+ s->timeout_start_usec = 0;
service_fix_output(s);
s->deserialized_state == SERVICE_FINAL_SIGTERM ||
s->deserialized_state == SERVICE_FINAL_SIGKILL ||
s->deserialized_state == SERVICE_AUTO_RESTART) {
-
- if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_usec > 0) {
+ if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
usec_t k;
- k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_usec;
+ k = s->deserialized_state == SERVICE_AUTO_RESTART ? s->restart_usec : s->timeout_start_usec;
if ((r = unit_watch_timer(UNIT(s), k, &s->timer_watch)) < 0)
return r;
}
}
- if (timeout && s->timeout_usec) {
- if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
+ if (timeout && s->timeout_start_usec) {
+ r = unit_watch_timer(UNIT(s), s->timeout_start_usec, &s->timer_watch);
+ if (r < 0)
goto fail;
} else
unit_unwatch_timer(UNIT(s), &s->timer_watch);
(s->restart == SERVICE_RESTART_ON_SUCCESS && s->result == SERVICE_SUCCESS) ||
(s->restart == SERVICE_RESTART_ON_FAILURE && s->result != SERVICE_SUCCESS) ||
(s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
- s->result == SERVICE_FAILURE_CORE_DUMP)))) {
+ s->result == SERVICE_FAILURE_CORE_DUMP))) &&
+ (s->result != SERVICE_FAILURE_EXIT_CODE ||
+ !set_contains(s->restart_ignore_status.code, INT_TO_PTR(s->main_exec_status.status))) &&
+ (s->result != SERVICE_FAILURE_SIGNAL ||
+ !set_contains(s->restart_ignore_status.signal, INT_TO_PTR(s->main_exec_status.status)))
+ ) {
r = unit_watch_timer(UNIT(s), s->restart_usec, &s->timer_watch);
if (r < 0)
}
if (wait_for_exit) {
- if (s->timeout_usec > 0)
- if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
+ if (s->timeout_stop_usec > 0) {
+ r = unit_watch_timer(UNIT(s), s->timeout_stop_usec, &s->timer_watch);
+ if (r < 0)
goto fail;
+ }
service_set_state(s, state);
} else if (state == SERVICE_STOP_SIGTERM || state == SERVICE_STOP_SIGKILL)
/* Make sure we don't enter a busy loop of some kind. */
r = service_start_limit_test(s);
if (r < 0) {
- service_notify_sockets_dead(s, true);
+ service_enter_dead(s, SERVICE_FAILURE_START_LIMIT, false);
return r;
}
assert(s);
assert(pid >= 0);
- if (UNIT(s)->fragment_path ? is_clean_exit(code, status) : is_clean_exit_lsb(code, status))
+ if (UNIT(s)->fragment_path ? is_clean_exit(code, status, &s->success_status) :
+ is_clean_exit_lsb(code, status, &s->success_status))
f = SERVICE_SUCCESS;
else if (code == CLD_EXITED)
f = SERVICE_FAILURE_EXIT_CODE;
[SERVICE_FAILURE_EXIT_CODE] = "exit-code",
[SERVICE_FAILURE_SIGNAL] = "signal",
[SERVICE_FAILURE_CORE_DUMP] = "core-dump",
- [SERVICE_FAILURE_WATCHDOG] = "watchdog"
+ [SERVICE_FAILURE_WATCHDOG] = "watchdog",
+ [SERVICE_FAILURE_START_LIMIT] = "start-limit"
};
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);