From 6cfe2fde1cc919c2333a5749ea1cbc31fa757077 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Jun 2014 18:42:52 +0200 Subject: [PATCH] core: introduce new Restart=on-abnormal setting Restart=on-abnormal is similar to Restart=on-failure, but avoids restarts on unclean exit codes (but still doing restarts on all obviously unclean exits, such as timeouts, signals, coredumps, watchdog timeouts). Also see: https://fedorahosted.org/fpc/ticket/191 --- man/systemd.service.xml | 153 ++++++++++++++++++++++++++++++++-------- src/core/service.c | 7 +- src/core/service.h | 1 + 3 files changed, 129 insertions(+), 32 deletions(-) diff --git a/man/systemd.service.xml b/man/systemd.service.xml index 74d974e6e..640318ba4 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -703,51 +703,146 @@ ExecStart=/bin/echo $ONE $TWO ${TWO} , , , + , , , or . If set to (the default), the - service will not be restarted. If set to - , it will be - restarted only when the service process - exits cleanly. - In this context, a clean exit means - an exit code of 0, or one of the signals + service will not be restarted. If set + to , it + will be restarted only when the + service process exits cleanly. In + this context, a clean exit means an + exit code of 0, or one of the signals SIGHUP, SIGINT, - SIGTERM, - or SIGPIPE, and - additionally, exit statuses and signals - specified in SuccessExitStatus=. + SIGTERM or + SIGPIPE, and + additionally, exit statuses and + signals specified in + SuccessExitStatus=. If set to , the service will be restarted when the - process exits with a non-zero exit code, - is terminated by a signal (including on - core dump), when an operation (such as - service reload) times out, and when the - configured watchdog timeout is triggered. - If set to - , the service - will be restarted only if the service - process exits due to an uncaught - signal not specified as a clean exit - status. - If set to - , the service - will be restarted only if the watchdog - timeout for the service expires. - If set to + process exits with a non-zero exit + code, is terminated by a signal + (including on core dump, but excluding + the aforementiond four signals), when + an operation (such as service reload) + times out, and when the configured + watchdog timeout is triggered. If set + to , the + service will be restarted when the + process is terminated by a signal + (including on core dump, excluding the + aforementioned four signals), when an + operation times out, or when the + watchdog timeout is triggered. If set + to , the + service will be restarted only if the + service process exits due to an + uncaught signal not specified as a + clean exit status. If set to + , the + service will be restarted only if the + watchdog timeout for the service + expires. If set to , the service - will be restarted regardless of whether - it exited cleanly or not, got + will be restarted regardless of + whether it exited cleanly or not, got terminated abnormally by a signal, or hit a timeout. + + Exit causes and the effect of the <varname>Restart=</varname> settings on them + + + + + + + Restart settings/Exit causes + + + + + + + + + + + + Clean exit code or signal + + X + X + + + + + + + Unclean exit code + + X + + X + + + + + + Unclean signal + + X + + X + X + X + + + + Timeout + + X + + X + X + + + + + Watchdog + + X + + X + X + + X + + + +
+ In addition to the above settings, the service will not be restarted if the exit code or signal is specified in RestartPreventExitStatus= - (see below). + (see below). + + Setting this to + is the + recommended choice for long-running + services, in order to increase + reliability by attempting automatic + recovery from errors. For services + that shall be able to terminate on + their own choice (and avoiding + immediate restart) + is an + alternative choice. + diff --git a/src/core/service.c b/src/core/service.c index 70e763511..244ec11f7 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1867,9 +1867,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_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 && (s->result == SERVICE_FAILURE_SIGNAL || - s->result == SERVICE_FAILURE_CORE_DUMP))) && + (s->restart == SERVICE_RESTART_ON_ABORT && IN_SET(s->result, SERVICE_FAILURE_SIGNAL, 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 || @@ -3790,9 +3790,10 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { [SERVICE_RESTART_NO] = "no", [SERVICE_RESTART_ON_SUCCESS] = "on-success", [SERVICE_RESTART_ON_FAILURE] = "on-failure", + [SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal", [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog", [SERVICE_RESTART_ON_ABORT] = "on-abort", - [SERVICE_RESTART_ALWAYS] = "always" + [SERVICE_RESTART_ALWAYS] = "always", }; DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); diff --git a/src/core/service.h b/src/core/service.h index 2254c3e0b..8c2c81925 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -53,6 +53,7 @@ typedef enum ServiceRestart { SERVICE_RESTART_NO, SERVICE_RESTART_ON_SUCCESS, SERVICE_RESTART_ON_FAILURE, + SERVICE_RESTART_ON_ABNORMAL, SERVICE_RESTART_ON_WATCHDOG, SERVICE_RESTART_ON_ABORT, SERVICE_RESTART_ALWAYS, -- 2.30.2