summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLukas Nykryn <lnykryn@redhat.com>2012-08-13 13:58:01 +0200
committerLennart Poettering <lennart@poettering.net>2012-08-14 14:46:03 +0200
commit96342de68d0d6de71a062d984dafd2a0905ed9fe (patch)
treeadbeb686c6c3c2bfd5a1c8768555575acb4850a2 /src/core
parentd98cc1f29fbf31ccc500d6e20c29b636b9af7e0f (diff)
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.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/mount.c2
-rw-r--r--src/core/service.c20
-rw-r--r--src/core/service.h3
-rw-r--r--src/core/socket.c2
-rw-r--r--src/core/swap.c2
6 files changed, 26 insertions, 5 deletions
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index e738213e27..84eea1c465 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -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')
diff --git a/src/core/mount.c b/src/core/mount.c
index 83e51a7aba..fc981c74f4 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -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;
diff --git a/src/core/service.c b/src/core/service.c
index e74da54eac..f540752b61 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -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;
diff --git a/src/core/service.h b/src/core/service.h
index c78de79a09..2a4dc30d0b 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -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;
diff --git a/src/core/socket.c b/src/core/socket.c
index 837b166e3b..cbbfb0cd3a 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -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;
diff --git a/src/core/swap.c b/src/core/swap.c
index 458e00efe5..cd4d9ab3d7 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -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;