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
This commit is contained in:
Lennart Poettering
2014-06-05 18:42:52 +02:00
parent 2d2ebaf515
commit 6cfe2fde1c
3 changed files with 129 additions and 32 deletions
+124 -29
View File
@@ -703,51 +703,146 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting>
<option>no</option>,
<option>on-success</option>,
<option>on-failure</option>,
<option>on-abnormal</option>,
<option>on-watchdog</option>,
<option>on-abort</option>, or
<option>always</option>. If set to
<option>no</option> (the default), the
service will not be restarted. If set to
<option>on-success</option>, 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 <option>on-success</option>, 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
<constant>SIGHUP</constant>,
<constant>SIGINT</constant>,
<constant>SIGTERM</constant>,
or <constant>SIGPIPE</constant>, and
additionally, exit statuses and signals
specified in <varname>SuccessExitStatus=</varname>.
<constant>SIGTERM</constant> or
<constant>SIGPIPE</constant>, and
additionally, exit statuses and
signals specified in
<varname>SuccessExitStatus=</varname>.
If set to <option>on-failure</option>,
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
<option>on-abort</option>, 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
<option>on-watchdog</option>, 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 <option>on-abnormal</option>, 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 <option>on-abort</option>, 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
<option>on-watchdog</option>, the
service will be restarted only if the
watchdog timeout for the service
expires. If set to
<option>always</option>, 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.</para>
<table>
<title>Exit causes and the effect of the <varname>Restart=</varname> settings on them</title>
<tgroup cols='2'>
<colspec colname='path' />
<colspec colname='expl' />
<thead>
<row>
<entry>Restart settings/Exit causes</entry>
<entry><option>no</option></entry>
<entry><option>always</option></entry>
<entry><option>on-success</option></entry>
<entry><option>on-failure</option></entry>
<entry><option>on-abnormal</option></entry>
<entry><option>on-abort</option></entry>
<entry><option>on-watchdog</option></entry>
</row>
</thead>
<tbody>
<row>
<entry>Clean exit code or signal</entry>
<entry/>
<entry>X</entry>
<entry>X</entry>
<entry/>
<entry/>
<entry/>
<entry/>
</row>
<row>
<entry>Unclean exit code</entry>
<entry/>
<entry>X</entry>
<entry/>
<entry>X</entry>
<entry/>
<entry/>
<entry/>
</row>
<row>
<entry>Unclean signal</entry>
<entry/>
<entry>X</entry>
<entry/>
<entry>X</entry>
<entry>X</entry>
<entry>X</entry>
<entry/>
</row>
<row>
<entry>Timeout</entry>
<entry/>
<entry>X</entry>
<entry/>
<entry>X</entry>
<entry>X</entry>
<entry/>
<entry/>
</row>
<row>
<entry>Watchdog</entry>
<entry/>
<entry>X</entry>
<entry/>
<entry>X</entry>
<entry>X</entry>
<entry/>
<entry>X</entry>
</row>
</tbody>
</tgroup>
</table>
<para>In addition to the above settings,
the service will not be restarted if the
exit code or signal is specified in
<varname>RestartPreventExitStatus=</varname>
(see below).</para></listitem>
(see below).</para>
<para>Setting this to
<option>on-failure</option> 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)
<option>on-abnormal</option> is an
alternative choice.</para>
</listitem>
</varlistentry>
<varlistentry>
+4 -3
View File
@@ -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);
+1
View File
@@ -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,