service: add options RestartPreventExitStatus and SuccessExitStatus

In some cases, like wrong configuration, restarting after error
does not help, so administrator can specify statuses by RestartPreventExitStatus
which will not cause restart of a service.

Sometimes you have non-standart exit status, so this can be specified
by SuccessfulExitStatus.
This commit is contained in:
Lukas Nykryn
2012-08-14 14:46:03 +02:00
committed by Lennart Poettering
parent d98cc1f29f
commit 96342de68d
18 changed files with 154 additions and 16 deletions
+2
View File
@@ -158,6 +158,8 @@ Service.PermissionsStartOnly, config_parse_bool, 0,
Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only)
Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit)
Service.GuessMainPID, config_parse_bool, 0, offsetof(Service, guess_main_pid)
Service.RestartPreventExitStatus, config_parse_set_status, 0, offsetof(Service, restart_ignore_status)
Service.SuccessExitStatus, config_parse_set_status, 0, offsetof(Service, success_status)
m4_ifdef(`HAVE_SYSV_COMPAT',
`Service.SysVStartPriority, config_parse_sysv_priority, 0, offsetof(Service, sysv_start_priority)',
`Service.SysVStartPriority, config_parse_warn_compat, 0, 0')
+1 -1
View File
@@ -1225,7 +1225,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
m->control_pid = 0;
if (is_clean_exit(code, status))
if (is_clean_exit(code, status, NULL))
f = MOUNT_SUCCESS;
else if (code == CLD_EXITED)
f = MOUNT_FAILURE_EXIT_CODE;
+18 -2
View File
@@ -294,6 +294,16 @@ static void service_done(Unit *u) {
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);
@@ -1902,7 +1912,12 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
(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)
@@ -2874,7 +2889,8 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
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;
+3
View File
@@ -28,6 +28,7 @@ typedef struct Service Service;
#include "ratelimit.h"
#include "service.h"
#include "kill.h"
#include "exit-status.h"
typedef enum ServiceState {
SERVICE_DEAD,
@@ -115,6 +116,8 @@ struct Service {
ServiceType type;
ServiceRestart restart;
ExitStatusSet restart_ignore_status;
ExitStatusSet success_status;
/* If set we'll read the main daemon PID from this file */
char *pid_file;
+1 -1
View File
@@ -1884,7 +1884,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
if (is_clean_exit(code, status))
if (is_clean_exit(code, status, NULL))
f = SOCKET_SUCCESS;
else if (code == CLD_EXITED)
f = SOCKET_FAILURE_EXIT_CODE;
+1 -1
View File
@@ -917,7 +917,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
if (is_clean_exit(code, status))
if (is_clean_exit(code, status, NULL))
f = SWAP_SUCCESS;
else if (code == CLD_EXITED)
f = SWAP_FAILURE_EXIT_CODE;