From a509f0e631b12cfec6aafe4d152532109082efc9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 28 Apr 2015 20:45:25 +0200 Subject: service: make restart logic a bit easier to understand --- src/core/service.c | 56 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/service.c b/src/core/service.c index d004728671..3a614b1c7a 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1268,6 +1268,49 @@ static int cgroup_good(Service *s) { return !r; } +static bool service_shall_restart(Service *s) { + assert(s); + + /* Don't restart after manual stops */ + if (s->forbid_restart) + return false; + + /* Never restart if this is configured as special exception */ + if (exit_status_set_test(&s->restart_prevent_status, s->main_exec_status.code, s->main_exec_status.status)) + return false; + + /* Restart if the exit code/status are configured as restart triggers */ + if (exit_status_set_test(&s->restart_force_status, s->main_exec_status.code, s->main_exec_status.status)) + return true; + + switch (s->restart) { + + case SERVICE_RESTART_NO: + return false; + + case SERVICE_RESTART_ALWAYS: + return true; + + case SERVICE_RESTART_ON_SUCCESS: + return s->result == SERVICE_SUCCESS; + + case SERVICE_RESTART_ON_FAILURE: + return s->result != SERVICE_SUCCESS; + + case SERVICE_RESTART_ON_ABNORMAL: + return !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE); + + case SERVICE_RESTART_ON_WATCHDOG: + return s->result == SERVICE_FAILURE_WATCHDOG; + + case SERVICE_RESTART_ON_ABORT: + return IN_SET(s->result, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP); + + default: + assert_not_reached("unknown restart setting"); + } +} + static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) { int r; assert(s); @@ -1282,16 +1325,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) failure_action(UNIT(s)->manager, s->failure_action, s->reboot_arg); } - if (allow_restart && - !s->forbid_restart && - (s->restart == SERVICE_RESTART_ALWAYS || - (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_ABNORMAL && !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE)) || - (s->restart == SERVICE_RESTART_ON_WATCHDOG && s->result == SERVICE_FAILURE_WATCHDOG) || - (s->restart == SERVICE_RESTART_ON_ABORT && IN_SET(s->result, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP)) || - exit_status_set_test(&s->restart_force_status, s->main_exec_status.code, s->main_exec_status.status)) && - !exit_status_set_test(&s->restart_prevent_status, s->main_exec_status.code, s->main_exec_status.status)) { + if (allow_restart && service_shall_restart(s)) { r = service_arm_timer(s, s->restart_usec); if (r < 0) @@ -1896,7 +1930,7 @@ static int service_stop(Unit *u) { assert(s); - /* Don't create restart jobs from here. */ + /* Don't create restart jobs from manual stops. */ s->forbid_restart = true; /* Already on it */ -- cgit v1.2.3-54-g00ecf