chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
service: Implement 'on-watchdog' restart option
[elogind.git]
/
src
/
core
/
service.c
diff --git
a/src/core/service.c
b/src/core/service.c
index 1dcd5cf44300bbf59dd1e2563b0bee4fcc938b04..08b929e4fe7af4b5ff4763c7177b9e13ef9f0460 100644
(file)
--- a/
src/core/service.c
+++ b/
src/core/service.c
@@
-191,6
+191,8
@@
static int service_set_main_pid(Service *s, pid_t pid) {
if (pid == getpid())
return -EINVAL;
if (pid == getpid())
return -EINVAL;
+ service_unwatch_main_pid(s);
+
s->main_pid = pid;
s->main_pid_known = true;
s->main_pid = pid;
s->main_pid_known = true;
@@
-983,7
+985,7
@@
static int service_load_sysv_name(Service *s, const char *name) {
assert(s);
assert(name);
assert(s);
assert(name);
- /* For SysV services we strip the *.sh suffixes. */
+
/* For SysV services we strip the *.sh suffixes. */
if (endswith(name, ".sh.service"))
return -ENOENT;
if (endswith(name, ".sh.service"))
return -ENOENT;
@@
-1111,6
+1113,12
@@
static int service_verify(Service *s) {
return -EINVAL;
}
return -EINVAL;
}
+ if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) {
+ log_error_unit(UNIT(s)->id,
+ "%s has Restart setting other than no, which isn't allowed for Type=oneshot services. Refusing.", UNIT(s)->id);
+ return -EINVAL;
+ }
+
if (s->type == SERVICE_DBUS && !s->bus_name) {
log_error_unit(UNIT(s)->id,
"%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id);
if (s->type == SERVICE_DBUS && !s->bus_name) {
log_error_unit(UNIT(s)->id,
"%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id);
@@
-1193,27
+1201,32
@@
static int service_load(Unit *u) {
assert(s);
/* Load a .service file */
assert(s);
/* Load a .service file */
- if ((r = unit_load_fragment(u)) < 0)
+ r = unit_load_fragment(u);
+ if (r < 0)
return r;
#ifdef HAVE_SYSV_COMPAT
/* Load a classic init script as a fallback, if we couldn't find anything */
return r;
#ifdef HAVE_SYSV_COMPAT
/* Load a classic init script as a fallback, if we couldn't find anything */
- if (u->load_state == UNIT_STUB)
- if ((r = service_load_sysv(s)) < 0)
+ if (u->load_state == UNIT_STUB) {
+ r = service_load_sysv(s);
+ if (r < 0)
return r;
return r;
+ }
#endif
/* Still nothing found? Then let's give up */
if (u->load_state == UNIT_STUB)
return -ENOENT;
#endif
/* Still nothing found? Then let's give up */
if (u->load_state == UNIT_STUB)
return -ENOENT;
- /* We were able to load something, then let's add in the
- * dropin directories. */
- if ((r = unit_load_dropin(unit_follow_merge(u))) < 0)
- return r;
-
/* This is a new unit? Then let's add in some extras */
if (u->load_state == UNIT_LOADED) {
/* This is a new unit? Then let's add in some extras */
if (u->load_state == UNIT_LOADED) {
+
+ /* We were able to load something, then let's add in
+ * the dropin directories. */
+ r = unit_load_dropin(u);
+ if (r < 0)
+ return r;
+
if (s->type == _SERVICE_TYPE_INVALID)
s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
if (s->type == _SERVICE_TYPE_INVALID)
s->type = s->bus_name ? SERVICE_DBUS : SERVICE_SIMPLE;
@@
-1612,6
+1625,7
@@
static int service_coldplug(Unit *u) {
s->deserialized_state == SERVICE_FINAL_SIGTERM ||
s->deserialized_state == SERVICE_FINAL_SIGKILL ||
s->deserialized_state == SERVICE_AUTO_RESTART) {
s->deserialized_state == SERVICE_FINAL_SIGTERM ||
s->deserialized_state == SERVICE_FINAL_SIGKILL ||
s->deserialized_state == SERVICE_AUTO_RESTART) {
+
if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
usec_t k;
if (s->deserialized_state == SERVICE_AUTO_RESTART || s->timeout_start_usec > 0) {
usec_t k;
@@
-1923,6
+1937,7
@@
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_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_WATCHDOG && s->result == SERVICE_FAILURE_WATCHDOG) ||
(s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
s->result == SERVICE_FAILURE_CORE_DUMP))) &&
(s->result != SERVICE_FAILURE_EXIT_CODE ||
(s->restart == SERVICE_RESTART_ON_ABORT && (s->result == SERVICE_FAILURE_SIGNAL ||
s->result == SERVICE_FAILURE_CORE_DUMP))) &&
(s->result != SERVICE_FAILURE_EXIT_CODE ||
@@
-1943,6
+1958,12
@@
static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
/* we want fresh tmpdirs in case service is started again immediately */
exec_context_tmp_dirs_done(&s->exec_context);
/* we want fresh tmpdirs in case service is started again immediately */
exec_context_tmp_dirs_done(&s->exec_context);
+ /* Try to delete the pid file. At this point it will be
+ * out-of-date, and some software might be confused by it, so
+ * let's remove it. */
+ if (s->pid_file)
+ unlink_noerrno(s->pid_file);
+
return;
fail:
return;
fail:
@@
-1981,7
+2002,7
@@
static void service_enter_stop_post(Service *s, ServiceResult f) {
service_set_state(s, SERVICE_STOP_POST);
} else
service_set_state(s, SERVICE_STOP_POST);
} else
- service_enter_
signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS
);
+ service_enter_
dead(s, SERVICE_SUCCESS, true
);
return;
return;
@@
-2139,7
+2160,6
@@
static void service_kill_control_processes(Service *s) {
return;
p = strappenda(UNIT(s)->cgroup_path, "/control");
return;
p = strappenda(UNIT(s)->cgroup_path, "/control");
-
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, true, true, true, NULL);
}
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, true, true, true, NULL);
}
@@
-2153,10
+2173,8
@@
static void service_enter_start(Service *s) {
assert(s->exec_command[SERVICE_EXEC_START]);
assert(!s->exec_command[SERVICE_EXEC_START]->command_next || s->type == SERVICE_ONESHOT);
assert(s->exec_command[SERVICE_EXEC_START]);
assert(!s->exec_command[SERVICE_EXEC_START]->command_next || s->type == SERVICE_ONESHOT);
- if (s->type == SERVICE_FORKING)
- service_unwatch_control_pid(s);
- else
- service_unwatch_main_pid(s);
+ service_unwatch_control_pid(s);
+ service_unwatch_main_pid(s);
/* We want to ensure that nobody leaks processes from
* START_PRE here, so let's go on a killing spree, People
/* We want to ensure that nobody leaks processes from
* START_PRE here, so let's go on a killing spree, People
@@
-3317,8
+3335,7
@@
static void service_notify_cgroup_empty_event(Unit *u) {
assert(u);
assert(u);
- log_debug_unit(u->id,
- "%s: cgroup is empty", u->id);
+ log_debug_unit(u->id, "%s: cgroup is empty", u->id);
switch (s->state) {
switch (s->state) {
@@
-3747,6
+3764,7
@@
static void service_reset_failed(Unit *u) {
static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
Service *s = SERVICE(u);
static int service_kill(Unit *u, KillWho who, int signo, DBusError *error) {
Service *s = SERVICE(u);
+
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
}
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
}
@@
-3774,6
+3792,7
@@
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_NO] = "no",
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
[SERVICE_RESTART_ON_FAILURE] = "on-failure",
+ [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog",
[SERVICE_RESTART_ON_ABORT] = "on-abort",
[SERVICE_RESTART_ALWAYS] = "always"
};
[SERVICE_RESTART_ON_ABORT] = "on-abort",
[SERVICE_RESTART_ALWAYS] = "always"
};
@@
-3886,6
+3905,8
@@
const UnitVTable service_vtable = {
.bus_set_property = bus_service_set_property,
.bus_commit_properties = bus_service_commit_properties,
.bus_set_property = bus_service_set_property,
.bus_commit_properties = bus_service_commit_properties,
+ .can_transient = true,
+
#ifdef HAVE_SYSV_COMPAT
.enumerate = service_enumerate,
#endif
#ifdef HAVE_SYSV_COMPAT
.enumerate = service_enumerate,
#endif