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:
committed by
Lennart Poettering
parent
d98cc1f29f
commit
96342de68d
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user