Merge pull request #29249 from poettering/pid1-error-message

pid1: refactoring of unit state machine logging and unit timer refactoring
This commit is contained in:
Luca Boccassi 2023-09-28 22:18:15 +01:00 committed by GitHub
commit 76dc9e249f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 458 additions and 430 deletions

View file

@ -82,7 +82,7 @@ static void unmount_autofs(Automount *a) {
if (a->where) {
r = repeat_unmount(a->where, MNT_DETACH|UMOUNT_NOFOLLOW);
if (r < 0)
log_error_errno(r, "Failed to unmount: %m");
log_unit_error_errno(UNIT(a), r, "Failed to unmount: %m");
}
}
}
@ -341,6 +341,7 @@ static void automount_enter_dead(Automount *a, AutomountResult f) {
static int open_dev_autofs(Manager *m) {
struct autofs_dev_ioctl param;
int r;
assert(m);
@ -354,9 +355,10 @@ static int open_dev_autofs(Manager *m) {
return log_error_errno(errno, "Failed to open /dev/autofs: %m");
init_autofs_dev_ioctl(&param);
if (ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param) < 0) {
r = RET_NERRNO(ioctl(m->dev_autofs_fd, AUTOFS_DEV_IOCTL_VERSION, &param));
if (r < 0) {
m->dev_autofs_fd = safe_close(m->dev_autofs_fd);
return -errno;
return log_error_errno(r, "Failed to issue AUTOFS_DEV_IOCTL_VERSION ioctl: %m");
}
log_debug("Autofs kernel version %u.%u", param.ver_major, param.ver_minor);
@ -556,8 +558,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
}
static void automount_enter_waiting(Automount *a) {
_cleanup_close_pair_ int pipe_fd[2] = PIPE_EBADF;
_cleanup_close_ int ioctl_fd = -EBADF;
int pipe_fd[2] = PIPE_EBADF;
char name[STRLEN("systemd-") + DECIMAL_STR_MAX(pid_t) + 1];
_cleanup_free_ char *options = NULL;
bool mounted = false;
@ -585,12 +587,14 @@ static void automount_enter_waiting(Automount *a) {
}
if (pipe2(pipe_fd, O_CLOEXEC) < 0) {
r = -errno;
r = log_unit_warning_errno(UNIT(a), errno, "Failed to allocate autofs pipe: %m");
goto fail;
}
r = fd_nonblock(pipe_fd[0], true);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(a), r, "Failed to make read side of pipe non-blocking: %m");
goto fail;
}
if (asprintf(
&options,
@ -599,12 +603,12 @@ static void automount_enter_waiting(Automount *a) {
getpgrp(),
isempty(a->extra_options) ? "" : ",",
strempty(a->extra_options)) < 0) {
r = -ENOMEM;
r = log_oom();
goto fail;
}
xsprintf(name, "systemd-"PID_FMT, getpid_cached());
r = mount_nofollow(name, a->where, "autofs", 0, options);
r = mount_nofollow_verbose(LOG_WARNING, name, a->where, "autofs", 0, options);
if (r < 0)
goto fail;
@ -613,46 +617,47 @@ static void automount_enter_waiting(Automount *a) {
pipe_fd[1] = safe_close(pipe_fd[1]);
if (stat(a->where, &st) < 0) {
r = -errno;
r = log_unit_warning_errno(UNIT(a), errno, "Failed to stat new automount point '%s': %m", a->where);
goto fail;
}
ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
if (ioctl_fd < 0) {
r = ioctl_fd;
r = log_unit_warning_errno(UNIT(a), ioctl_fd, "Failed to open automount ioctl fd for '%s': %m", a->where);
goto fail;
}
r = autofs_protocol(dev_autofs_fd, ioctl_fd);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(a), r, "Failed to validate autofs protocol for '%s': %m", a->where);
goto fail;
}
r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(a), r, "Failed to set autofs timeout for '%s': %m", a->where);
goto fail;
}
r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, pipe_fd[0], EPOLLIN, automount_dispatch_io, a);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(a), r, "Failed to allocate IO event source for autofs mount '%s': %m", a->where);
goto fail;
}
(void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
a->pipe_fd = pipe_fd[0];
a->pipe_fd = TAKE_FD(pipe_fd[0]);
a->dev_id = st.st_dev;
automount_set_state(a, AUTOMOUNT_WAITING);
return;
fail:
log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");
safe_close_pair(pipe_fd);
if (mounted) {
r = repeat_unmount(a->where, MNT_DETACH|UMOUNT_NOFOLLOW);
if (r < 0)
log_error_errno(r, "Failed to unmount, ignoring: %m");
log_unit_warning_errno(UNIT(a), r, "Failed to unmount, ignoring: %m");
}
automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);

View file

@ -191,34 +191,10 @@ static void mount_init(Unit *u) {
u->ignore_on_isolate = true;
}
static int mount_arm_timer(Mount *m, usec_t usec) {
int r;
static int mount_arm_timer(Mount *m, bool relative, usec_t usec) {
assert(m);
if (usec == USEC_INFINITY)
return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_OFF);
if (m->timer_event_source) {
r = sd_event_source_set_time(m->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(m->timer_event_source, SD_EVENT_ONESHOT);
}
r = sd_event_add_time(
UNIT(m)->manager->event,
&m->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
mount_dispatch_timer, m);
if (r < 0)
return r;
(void) sd_event_source_set_description(m->timer_event_source, "mount-timer");
return 0;
return unit_arm_timer(UNIT(m), &m->timer_event_source, relative, usec, mount_dispatch_timer);
}
static void mount_unwatch_control_pid(Mount *m) {
@ -809,7 +785,7 @@ static int mount_coldplug(Unit *u) {
if (r < 0)
return r;
r = mount_arm_timer(m, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec));
r = mount_arm_timer(m, /* relative= */ false, usec_add(u->state_change_timestamp.monotonic, m->timeout_usec));
if (r < 0)
return r;
}
@ -932,7 +908,7 @@ static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) {
if (r < 0)
return r;
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
r = mount_arm_timer(m, /* relative= */ true, m->timeout_usec);
if (r < 0)
return r;
@ -1039,13 +1015,17 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
/* main_pid= */ NULL,
&m->control_pid,
/* main_pid_alien= */ false);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m");
goto fail;
}
if (r > 0) {
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->timeout_usec));
if (r < 0)
r = mount_arm_timer(m, /* relative= */ true, m->timeout_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to install timer: %m");
goto fail;
}
mount_set_state(m, state);
} else if (state == MOUNT_REMOUNTING_SIGTERM && m->kill_context.send_sigkill)
@ -1060,10 +1040,34 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
return;
fail:
log_unit_warning_errno(UNIT(m), r, "Failed to kill processes: %m");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
}
static int mount_set_umount_command(Mount *m, ExecCommand *c) {
int r;
assert(m);
assert(c);
r = exec_command_set(c, UMOUNT_PATH, m->where, "-c", NULL);
if (r < 0)
return r;
if (m->lazy_unmount) {
r = exec_command_append(c, "-l", NULL);
if (r < 0)
return r;
}
if (m->force_unmount) {
r = exec_command_append(c, "-f", NULL);
if (r < 0)
return r;
}
return 0;
}
static void mount_enter_unmounting(Mount *m) {
int r;
@ -1079,29 +1083,71 @@ static void mount_enter_unmounting(Mount *m) {
m->control_command_id = MOUNT_EXEC_UNMOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
r = exec_command_set(m->control_command, UMOUNT_PATH, m->where, "-c", NULL);
if (r >= 0 && m->lazy_unmount)
r = exec_command_append(m->control_command, "-l", NULL);
if (r >= 0 && m->force_unmount)
r = exec_command_append(m->control_command, "-f", NULL);
if (r < 0)
r = mount_set_umount_command(m, m->control_command);
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to prepare umount command line: %m");
goto fail;
}
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to spawn 'umount' task: %m");
goto fail;
}
mount_set_state(m, MOUNT_UNMOUNTING);
return;
fail:
log_unit_warning_errno(UNIT(m), r, "Failed to run 'umount' task: %m");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
}
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p) {
int r;
assert(m);
assert(c);
assert(p);
r = exec_command_set(c, MOUNT_PATH, p->what, m->where, NULL);
if (r < 0)
return r;
if (m->sloppy_options) {
r = exec_command_append(c, "-s", NULL);
if (r < 0)
return r;
}
if (m->read_write_only) {
r = exec_command_append(c, "-w", NULL);
if (r < 0)
return r;
}
if (p->fstype) {
r = exec_command_append(c, "-t", p->fstype, NULL);
if (r < 0)
return r;
}
_cleanup_free_ char *opts = NULL;
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, NULL, &opts);
if (r < 0)
return r;
if (!isempty(opts)) {
r = exec_command_append(c, "-o", opts, NULL);
if (r < 0)
return r;
}
return 0;
}
static void mount_enter_mounting(Mount *m) {
int r;
MountParameters *p;
@ -1148,38 +1194,28 @@ static void mount_enter_mounting(Mount *m) {
}
if (p) {
_cleanup_free_ char *opts = NULL;
r = fstab_filter_options(p->options, "nofail\0" "noauto\0" "auto\0", NULL, NULL, NULL, &opts);
if (r < 0)
r = mount_set_mount_command(m, m->control_command, p);
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to prepare mount command line: %m");
goto fail;
r = exec_command_set(m->control_command, MOUNT_PATH, p->what, m->where, NULL);
if (r >= 0 && m->sloppy_options)
r = exec_command_append(m->control_command, "-s", NULL);
if (r >= 0 && m->read_write_only)
r = exec_command_append(m->control_command, "-w", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
if (r >= 0 && !isempty(opts))
r = exec_command_append(m->control_command, "-o", opts, NULL);
} else
r = -ENOENT;
if (r < 0)
}
} else {
r = log_unit_warning_errno(UNIT(m), SYNTHETIC_ERRNO(ENOENT), "No mount parameters to operate on.");
goto fail;
}
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to spawn 'mount' task: %m");
goto fail;
}
mount_set_state(m, MOUNT_MOUNTING);
return;
fail:
log_unit_warning_errno(UNIT(m), r, "Failed to run 'mount' task: %m");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
}
@ -1223,23 +1259,28 @@ static void mount_enter_remounting(Mount *m) {
r = exec_command_append(m->control_command, "-w", NULL);
if (r >= 0 && p->fstype)
r = exec_command_append(m->control_command, "-t", p->fstype, NULL);
} else
r = -ENOENT;
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to prepare remount command line: %m");
goto fail;
}
} else {
r = log_unit_warning_errno(UNIT(m), SYNTHETIC_ERRNO(ENOENT), "No mount parameters to operate on.");
goto fail;
}
mount_unwatch_control_pid(m);
r = mount_spawn(m, m->control_command, &m->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(m), r, "Failed to spawn 'remount' task: %m");
goto fail;
}
mount_set_state(m, MOUNT_REMOUNTING);
return;
fail:
log_unit_warning_errno(UNIT(m), r, "Failed to run 'remount' task: %m");
mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
}
@ -2240,19 +2281,22 @@ static int mount_clean(Unit *u, ExecCleanMask mask) {
m->control_command = NULL;
m->control_command_id = _MOUNT_EXEC_COMMAND_INVALID;
r = mount_arm_timer(m, usec_add(now(CLOCK_MONOTONIC), m->exec_context.timeout_clean_usec));
if (r < 0)
r = mount_arm_timer(m, /* relative= */ true, m->exec_context.timeout_clean_usec);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to install timer: %m");
goto fail;
}
r = unit_fork_and_watch_rm_rf(u, l, &m->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to spawn cleaning task: %m");
goto fail;
}
mount_set_state(m, MOUNT_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
m->clean_result = MOUNT_FAILURE_RESOURCES;
m->timer_event_source = sd_event_source_disable_unref(m->timer_event_source);
return r;

View file

@ -530,23 +530,26 @@ static void path_enter_running(Path *p, char *trigger_path) {
trigger = UNIT_TRIGGER(UNIT(p));
if (!trigger) {
log_unit_error(UNIT(p), "Unit to trigger vanished.");
path_enter_dead(p, PATH_FAILURE_RESOURCES);
return;
goto fail;
}
details = activation_details_new(UNIT(p));
if (!details) {
r = -ENOMEM;
log_oom();
goto fail;
}
r = free_and_strdup(&(ACTIVATION_DETAILS_PATH(details))->trigger_path_filename, trigger_path);
if (r < 0)
if (r < 0) {
log_oom();
goto fail;
}
r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, &job);
if (r < 0)
if (r < 0) {
log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
goto fail;
}
job_set_activation_details(job, details);
@ -556,7 +559,6 @@ static void path_enter_running(Path *p, char *trigger_path) {
return;
fail:
log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
path_enter_dead(p, PATH_FAILURE_RESOURCES);
}
@ -594,8 +596,11 @@ static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify)
}
r = path_watch(p);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m");
path_enter_dead(p, PATH_FAILURE_RESOURCES);
return;
}
/* Hmm, so now we have created inotify watches, but the file
* might have appeared/been removed by now, so we must
@ -608,11 +613,6 @@ static void path_enter_waiting(Path *p, bool initial, bool from_trigger_notify)
}
path_set_state(p, PATH_WAITING);
return;
fail:
log_unit_warning_errno(UNIT(p), r, "Failed to enter waiting state: %m");
path_enter_dead(p, PATH_FAILURE_RESOURCES);
}
static void path_mkdir(Path *p) {

View file

@ -76,34 +76,10 @@ static usec_t scope_running_timeout(Scope *s) {
delta);
}
static int scope_arm_timer(Scope *s, usec_t usec) {
int r;
static int scope_arm_timer(Scope *s, bool relative, usec_t usec) {
assert(s);
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
r = sd_event_add_time(
UNIT(s)->manager->event,
&s->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
scope_dispatch_timer, s);
if (r < 0)
return r;
(void) sd_event_source_set_description(s->timer_event_source, "scope-timer");
return 0;
return unit_arm_timer(UNIT(s), &s->timer_event_source, relative, usec, scope_dispatch_timer);
}
static void scope_set_state(Scope *s, ScopeState state) {
@ -260,7 +236,7 @@ static int scope_coldplug(Unit *u) {
if (s->deserialized_state == s->state)
return 0;
r = scope_arm_timer(s, scope_coldplug_timeout(s));
r = scope_arm_timer(s, /* relative= */ false, scope_coldplug_timeout(s));
if (r < 0)
return r;
@ -348,14 +324,18 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
/* main_pid= */ NULL,
/* control_pid= */ NULL,
/* main_pid_alien= */ false);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
goto fail;
}
}
if (r > 0) {
r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
if (r < 0)
r = scope_arm_timer(s, /* relative= */ true, s->timeout_stop_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
goto fail;
}
scope_set_state(s, state);
} else if (state == SCOPE_STOP_SIGTERM)
@ -366,8 +346,6 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
}
@ -379,7 +357,7 @@ static int scope_enter_start_chown(Scope *s) {
assert(s);
assert(s->user);
r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), u->manager->defaults.timeout_start_usec));
r = scope_arm_timer(s, /* relative= */ true, u->manager->defaults.timeout_start_usec);
if (r < 0)
return r;
@ -462,7 +440,7 @@ static int scope_enter_running(Scope *s) {
scope_set_state(s, SCOPE_RUNNING);
/* Set the maximum runtime timeout. */
scope_arm_timer(s, scope_running_timeout(s));
scope_arm_timer(s, /* relative= */ false, scope_running_timeout(s));
/* On unified we use proper notifications hence we can unwatch the PIDs
* we just attached to the scope. This can also be done on legacy as

View file

@ -620,33 +620,9 @@ static usec_t service_running_timeout(Service *s) {
}
static int service_arm_timer(Service *s, bool relative, usec_t usec) {
int r;
assert(s);
if (s->timer_event_source) {
r = (relative ? sd_event_source_set_time_relative : sd_event_source_set_time)(s->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
r = (relative ? sd_event_add_time_relative : sd_event_add_time)(
UNIT(s)->manager->event,
&s->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
service_dispatch_timer, s);
if (r < 0)
return r;
(void) sd_event_source_set_description(s->timer_event_source, "service-timer");
return 0;
return unit_arm_timer(UNIT(s), &s->timer_event_source, relative, usec, service_dispatch_timer);
}
static int service_verify(Service *s) {
@ -2037,8 +2013,11 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
restart_usec_next = service_restart_usec_next(s);
r = service_arm_timer(s, /* relative= */ true, restart_usec_next);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install restart timer: %m");
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ false);
return;
}
log_unit_debug(UNIT(s), "Next restart interval calculated as: %s", FORMAT_TIMESPAN(restart_usec_next, 0));
@ -2082,12 +2061,6 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
/* Reset TTY ownership if necessary */
exec_context_revert_tty(&s->exec_context);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run install restart timer: %m");
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
}
static void service_enter_stop_post(Service *s, ServiceResult f) {
@ -2110,18 +2083,15 @@ static void service_enter_stop_post(Service *s, ServiceResult f) {
s->timeout_stop_usec,
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP,
&s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop-post' task: %m");
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
return;
}
service_set_state(s, SERVICE_STOP_POST);
} else
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m");
service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static int state_to_kill_operation(Service *s, ServiceState state) {
@ -2171,14 +2141,18 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
&s->main_pid,
&s->control_pid,
s->main_pid_alien);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
goto fail;
}
if (r > 0) {
r = service_arm_timer(s, /* relative= */ true,
kill_operation == KILL_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
goto fail;
}
service_set_state(s, state);
} else if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM) && s->kill_context.send_sigkill)
@ -2188,25 +2162,30 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
else if (IN_SET(state, SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM) && s->kill_context.send_sigkill)
service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS);
else
service_enter_dead(s, SERVICE_SUCCESS, true);
service_enter_dead(s, SERVICE_SUCCESS, /* allow_restart= */ true);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
if (IN_SET(state, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL))
service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES);
else
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ true);
}
static void service_enter_stop_by_notify(Service *s) {
int r;
assert(s);
(void) unit_enqueue_rewatch_pids(UNIT(s));
service_arm_timer(s, /* relative= */ true, s->timeout_stop_usec);
r = service_arm_timer(s, /* relative= */ true, s->timeout_stop_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
return;
}
/* The service told us it's stopping, so it's as if we SIGTERM'd it. */
service_set_state(s, SERVICE_STOP_SIGTERM);
@ -2233,18 +2212,15 @@ static void service_enter_stop(Service *s, ServiceResult f) {
s->timeout_stop_usec,
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT|EXEC_CONTROL_CGROUP,
&s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop' task: %m");
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
return;
}
service_set_state(s, SERVICE_STOP);
} else
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop' task: %m");
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
static bool service_good(Service *s) {
@ -2268,6 +2244,8 @@ static bool service_good(Service *s) {
}
static void service_enter_running(Service *s, ServiceResult f) {
int r;
assert(s);
if (s->result == SERVICE_SUCCESS)
@ -2286,7 +2264,13 @@ static void service_enter_running(Service *s, ServiceResult f) {
service_enter_stop_by_notify(s);
else {
service_set_state(s, SERVICE_RUNNING);
service_arm_timer(s, /* relative= */ false, service_running_timeout(s));
r = service_arm_timer(s, /* relative= */ false, service_running_timeout(s));
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
service_enter_running(s, SERVICE_FAILURE_RESOURCES);
return;
}
}
} else if (s->remain_after_exit)
@ -2312,18 +2296,15 @@ static void service_enter_start_post(Service *s) {
s->timeout_start_usec,
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP,
&s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-post' task: %m");
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
return;
}
service_set_state(s, SERVICE_START_POST);
} else
service_enter_running(s, SERVICE_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m");
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
static void service_kill_control_process(Service *s) {
@ -2425,8 +2406,10 @@ static void service_enter_start(Service *s) {
timeout,
EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_WRITE_CREDENTIALS|EXEC_SETENV_MONITOR_RESULT,
&pidref);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start' task: %m");
goto fail;
}
if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)) {
/* For simple services we immediately start
@ -2459,7 +2442,6 @@ static void service_enter_start(Service *s) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m");
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
}
@ -2484,8 +2466,10 @@ static void service_enter_start_pre(Service *s) {
s->timeout_start_usec,
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN|EXEC_SETENV_MONITOR_RESULT|EXEC_WRITE_CREDENTIALS,
&s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-pre' task: %m");
goto fail;
}
service_set_state(s, SERVICE_START_PRE);
} else
@ -2494,8 +2478,7 @@ static void service_enter_start_pre(Service *s) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m");
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ true);
}
static void service_enter_condition(Service *s) {
@ -2521,8 +2504,10 @@ static void service_enter_condition(Service *s) {
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN,
&s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'exec-condition' task: %m");
goto fail;
}
service_set_state(s, SERVICE_CONDITION);
} else
@ -2531,8 +2516,7 @@ static void service_enter_condition(Service *s) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'exec-condition' task: %m");
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ true);
}
static void service_enter_restart(Service *s) {
@ -2550,8 +2534,11 @@ static void service_enter_restart(Service *s) {
/* Any units that are bound to this service must also be restarted. We use JOB_START for ourselves
* but then set JOB_RESTART_DEPENDENCIES which will enqueue JOB_RESTART for those dependency jobs. */
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(s), JOB_RESTART_DEPENDENCIES, NULL, &error, NULL);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, r));
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ false);
return;
}
/* Count the jobs we enqueue for restarting. This counter is maintained as long as the unit isn't
* fully stopped, i.e. as long as it remains up or remains in auto-start states. The user can reset
@ -2572,11 +2559,6 @@ static void service_enter_restart(Service *s) {
/* Notify clients about changed restart counter */
unit_add_to_dbus_queue(UNIT(s));
return;
fail:
log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, r));
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false);
}
static void service_enter_reload_by_notify(Service *s) {
@ -2585,13 +2567,20 @@ static void service_enter_reload_by_notify(Service *s) {
assert(s);
service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
r = service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
s->reload_result = SERVICE_FAILURE_RESOURCES;
service_enter_running(s, SERVICE_SUCCESS);
return;
}
service_set_state(s, SERVICE_RELOAD_NOTIFY);
/* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */
r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error);
if (r < 0)
log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, r));
log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", bus_error_message(&error, r));
}
static void service_enter_reload(Service *s) {
@ -2626,13 +2615,18 @@ static void service_enter_reload(Service *s) {
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP,
&s->control_pid);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m");
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'reload' task: %m");
goto fail;
}
service_set_state(s, SERVICE_RELOAD);
} else if (killed) {
service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
r = service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
goto fail;
}
service_set_state(s, SERVICE_RELOAD_SIGNAL);
} else {
service_enter_running(s, SERVICE_SUCCESS);
@ -2681,23 +2675,19 @@ static void service_run_next_control(Service *s) {
(IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_START) ? EXEC_SETENV_MONITOR_RESULT : 0)|
(IN_SET(s->control_command_id, SERVICE_EXEC_START_POST, SERVICE_EXEC_RELOAD, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_CONTROL_CGROUP : 0),
&s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn next control task: %m");
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m");
if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
else if (s->state == SERVICE_RELOAD) {
s->reload_result = SERVICE_FAILURE_RESOURCES;
service_enter_running(s, SERVICE_SUCCESS);
} else
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ true);
else if (s->state == SERVICE_RELOAD) {
s->reload_result = SERVICE_FAILURE_RESOURCES;
service_enter_running(s, SERVICE_SUCCESS);
} else
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
}
static void service_run_next_main(Service *s) {
@ -2717,15 +2707,13 @@ static void service_run_next_main(Service *s) {
s->timeout_start_usec,
EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG|EXEC_SETENV_MONITOR_RESULT|EXEC_WRITE_CREDENTIALS,
&pidref);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn next main task: %m");
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
return;
}
(void) service_set_main_pidref(s, &pidref);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next main task: %m");
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
}
static int service_start(Unit *u) {
@ -3487,18 +3475,17 @@ static int service_watch_pid_file(Service *s) {
log_unit_debug(UNIT(s), "Setting watch for PID file %s", s->pid_file_pathspec->path);
r = path_spec_watch(s->pid_file_pathspec, service_dispatch_inotify_io);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_error_errno(UNIT(s), r, "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec->path);
service_unwatch_pid_file(s);
return r;
}
/* the pidfile might have appeared just before we set the watch */
log_unit_debug(UNIT(s), "Trying to read PID file %s in case it changed", s->pid_file_pathspec->path);
service_retry_pid_file(s);
return 0;
fail:
log_unit_error_errno(UNIT(s), r, "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec->path);
service_unwatch_pid_file(s);
return r;
}
static int service_demand_pid_file(Service *s) {
@ -4929,18 +4916,21 @@ static int service_clean(Unit *u, ExecCleanMask mask) {
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
r = service_arm_timer(s, /* relative= */ true, s->exec_context.timeout_clean_usec);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to install timer: %m");
goto fail;
}
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to spawn cleaning task: %m");
goto fail;
}
service_set_state(s, SERVICE_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SERVICE_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
return r;

View file

@ -182,34 +182,10 @@ static void socket_done(Unit *u) {
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
}
static int socket_arm_timer(Socket *s, usec_t usec) {
int r;
static int socket_arm_timer(Socket *s, bool relative, usec_t usec) {
assert(s);
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
r = sd_event_add_time(
UNIT(s)->manager->event,
&s->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
socket_dispatch_timer, s);
if (r < 0)
return r;
(void) sd_event_source_set_description(s->timer_event_source, "socket-timer");
return 0;
return unit_arm_timer(UNIT(s), &s->timer_event_source, relative, usec, socket_dispatch_timer);
}
static bool have_non_accept_socket(Socket *s) {
@ -506,7 +482,7 @@ static SocketPeer *socket_peer_free(SocketPeer *p) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free);
int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
int socket_acquire_peer(Socket *s, int fd, SocketPeer **ret) {
_cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL;
SocketPeer sa = {
.peer_salen = sizeof(union sockaddr_union),
@ -515,22 +491,19 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
assert(fd >= 0);
assert(s);
assert(ret);
if (getpeername(fd, &sa.peer.sa, &sa.peer_salen) < 0)
return log_unit_error_errno(UNIT(s), errno, "getpeername failed: %m");
return log_unit_error_errno(UNIT(s), errno, "getpeername() failed: %m");
if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
*p = NULL;
*ret = NULL;
return 0;
}
r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
if (r < 0)
return r;
i = set_get(s->peers_by_address, &sa);
if (i) {
*p = socket_peer_ref(i);
*ret = socket_peer_ref(i);
return 1;
}
@ -541,13 +514,13 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
remote->peer = sa.peer;
remote->peer_salen = sa.peer_salen;
r = set_put(s->peers_by_address, remote);
r = set_ensure_put(&s->peers_by_address, &peer_address_hash_ops, remote);
if (r < 0)
return r;
return log_unit_error_errno(UNIT(s), r, "Failed to insert peer info into hash table: %m");
remote->socket = s;
*p = TAKE_PTR(remote);
*ret = TAKE_PTR(remote);
return 1;
}
@ -1896,7 +1869,7 @@ static int socket_coldplug(Unit *u) {
if (r < 0)
return r;
r = socket_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
r = socket_arm_timer(s, /* relative= */ false, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
if (r < 0)
return r;
}
@ -1959,7 +1932,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, PidRef *ret_pid) {
if (r < 0)
return r;
r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
r = socket_arm_timer(s, /* relative= */ true, s->timeout_usec);
if (r < 0)
return r;
@ -1995,7 +1968,7 @@ static int socket_chown(Socket *s, PidRef *ret_pid) {
assert(s);
r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
r = socket_arm_timer(s, /* relative= */ true, s->timeout_usec);
if (r < 0)
return r;
@ -2098,18 +2071,15 @@ static void socket_enter_stop_post(Socket *s, SocketResult f) {
pidref_done(&s->control_pid);
r = socket_spawn(s, s->control_command, &s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop-post' task: %m");
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
return;
}
socket_set_state(s, SOCKET_STOP_POST);
} else
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m");
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
}
static int state_to_kill_operation(Socket *s, SocketState state) {
@ -2137,13 +2107,17 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
/* main_pid= */ NULL,
&s->control_pid,
/* main_pid_alien= */ false);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
goto fail;
}
if (r > 0) {
r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
r = socket_arm_timer(s, /* relative= */ true, s->timeout_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
goto fail;
}
socket_set_state(s, state);
} else if (state == SOCKET_STOP_PRE_SIGTERM)
@ -2158,8 +2132,6 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
if (IN_SET(state, SOCKET_STOP_PRE_SIGTERM, SOCKET_STOP_PRE_SIGKILL))
socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
else
@ -2181,18 +2153,15 @@ static void socket_enter_stop_pre(Socket *s, SocketResult f) {
pidref_done(&s->control_pid);
r = socket_spawn(s, s->control_command, &s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'stop-pre' task: %m");
socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
return;
}
socket_set_state(s, SOCKET_STOP_PRE);
} else
socket_enter_stop_post(s, SOCKET_SUCCESS);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-pre' task: %m");
socket_enter_stop_post(s, SOCKET_FAILURE_RESOURCES);
}
static void socket_enter_listening(Socket *s) {
@ -2207,14 +2176,11 @@ static void socket_enter_listening(Socket *s) {
r = socket_watch_fds(s);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m");
goto fail;
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
return;
}
socket_set_state(s, SOCKET_LISTENING);
return;
fail:
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
}
static void socket_enter_start_post(Socket *s) {
@ -2230,18 +2196,14 @@ static void socket_enter_start_post(Socket *s) {
r = socket_spawn(s, s->control_command, &s->control_pid);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m");
goto fail;
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-post' task: %m");
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
return;
}
socket_set_state(s, SOCKET_START_POST);
} else
socket_enter_listening(s);
return;
fail:
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
}
static void socket_enter_start_chown(Socket *s) {
@ -2263,7 +2225,7 @@ static void socket_enter_start_chown(Socket *s) {
r = socket_chown(s, &s->control_pid);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to fork 'start-chown' task: %m");
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-chown' task: %m");
goto fail;
}
@ -2293,18 +2255,14 @@ static void socket_enter_start_pre(Socket *s) {
r = socket_spawn(s, s->control_command, &s->control_pid);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m");
goto fail;
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'start-pre' task: %m");
socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
return;
}
socket_set_state(s, SOCKET_START_PRE);
} else
socket_enter_start_chown(s);
return;
fail:
socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
}
static void flush_ports(Socket *s) {
@ -2350,7 +2308,7 @@ static void socket_enter_running(Socket *s, int cfd_in) {
goto refuse;
}
if (cfd < 0) {
if (cfd < 0) { /* Accept=no case */
bool pending = false;
Unit *other;
@ -2363,18 +2321,18 @@ static void socket_enter_running(Socket *s, int cfd_in) {
if (!pending) {
if (!UNIT_ISSET(s->service)) {
r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT),
"Service to activate vanished, refusing activation.");
r = log_unit_warning_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT),
"Service to activate vanished, refusing activation.");
goto fail;
}
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, NULL, &error, NULL);
if (r < 0)
goto fail;
goto queue_error;
}
socket_set_state(s, SOCKET_RUNNING);
} else {
} else { /* Accept=yes case */
_cleanup_(socket_peer_unrefp) SocketPeer *p = NULL;
Unit *service;
@ -2408,13 +2366,17 @@ static void socket_enter_running(Socket *s, int cfd_in) {
if (r < 0) {
if (ERRNO_IS_DISCONNECT(r))
return;
log_unit_warning_errno(UNIT(s), r, "Failed to load connection service unit: %m");
goto fail;
}
r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service,
false, UNIT_DEPENDENCY_IMPLICIT);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to add Before=/Triggers= dependencies on connection unit: %m");
goto fail;
}
s->n_accepted++;
@ -2422,6 +2384,8 @@ static void socket_enter_running(Socket *s, int cfd_in) {
if (r < 0) {
if (ERRNO_IS_DISCONNECT(r))
return;
log_unit_warning_errno(UNIT(s), r, "Failed to set socket on service: %m");
goto fail;
}
@ -2433,21 +2397,20 @@ static void socket_enter_running(Socket *s, int cfd_in) {
/* We failed to activate the new service, but it still exists. Let's make sure the
* service closes and forgets the connection fd again, immediately. */
service_release_socket_fd(SERVICE(service));
goto fail;
goto queue_error;
}
/* Notify clients about changed counters */
unit_add_to_dbus_queue(UNIT(s));
}
TAKE_FD(cfd);
return;
refuse:
s->n_refused++;
return;
fail:
queue_error:
if (ERRNO_IS_RESOURCE(r))
log_unit_warning(UNIT(s), "Failed to queue service startup job: %s",
bus_error_message(&error, r));
@ -2456,6 +2419,7 @@ fail:
cfd >= 0 ? "template" : "non-template",
bus_error_message(&error, r));
fail:
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
}
@ -2473,20 +2437,16 @@ static void socket_run_next(Socket *s) {
pidref_done(&s->control_pid);
r = socket_spawn(s, s->control_command, &s->control_pid);
if (r < 0)
goto fail;
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn next task: %m");
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next task: %m");
if (s->state == SOCKET_START_POST)
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
else if (s->state == SOCKET_STOP_POST)
socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
else
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
if (s->state == SOCKET_START_POST)
socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
else if (s->state == SOCKET_STOP_POST)
socket_enter_dead(s, SOCKET_FAILURE_RESOURCES);
else
socket_enter_signal(s, SOCKET_FINAL_SIGTERM, SOCKET_FAILURE_RESOURCES);
}
}
static int socket_start(Unit *u) {
@ -3454,19 +3414,22 @@ static int socket_clean(Unit *u, ExecCleanMask mask) {
s->control_command = NULL;
s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
r = socket_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
if (r < 0)
r = socket_arm_timer(s, /* relative= */ true, s->exec_context.timeout_clean_usec);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to install timer: %m");
goto fail;
}
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to spawn cleaning task: %m");
goto fail;
}
socket_set_state(s, SOCKET_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SOCKET_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
return r;

View file

@ -181,34 +181,10 @@ static void swap_done(Unit *u) {
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
}
static int swap_arm_timer(Swap *s, usec_t usec) {
int r;
static int swap_arm_timer(Swap *s, bool relative, usec_t usec) {
assert(s);
if (s->timer_event_source) {
r = sd_event_source_set_time(s->timer_event_source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
r = sd_event_add_time(
UNIT(s)->manager->event,
&s->timer_event_source,
CLOCK_MONOTONIC,
usec, 0,
swap_dispatch_timer, s);
if (r < 0)
return r;
(void) sd_event_source_set_description(s->timer_event_source, "swap-timer");
return 0;
return unit_arm_timer(UNIT(s), &s->timer_event_source, relative, usec, swap_dispatch_timer);
}
static SwapParameters* swap_get_parameters(Swap *s) {
@ -435,12 +411,14 @@ static int swap_setup_unit(
delete = true;
r = unit_new_for_name(m, sizeof(Swap), e, &u);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
goto fail;
}
SWAP(u)->what = strdup(what);
if (!SWAP(u)->what) {
r = -ENOMEM;
r = log_oom();
goto fail;
}
@ -453,7 +431,7 @@ static int swap_setup_unit(
if (!p->what) {
p->what = strdup(what_proc_swaps);
if (!p->what) {
r = -ENOMEM;
r = log_oom();
goto fail;
}
}
@ -479,8 +457,6 @@ static int swap_setup_unit(
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to load swap unit: %m");
if (delete)
unit_free(u);
@ -588,7 +564,7 @@ static int swap_coldplug(Unit *u) {
if (r < 0)
return r;
r = swap_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
r = swap_arm_timer(s, /* relative= */ false, usec_add(u->state_change_timestamp.monotonic, s->timeout_usec));
if (r < 0)
return r;
}
@ -675,7 +651,7 @@ static int swap_spawn(Swap *s, ExecCommand *c, PidRef *ret_pid) {
if (r < 0)
return r;
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
r = swap_arm_timer(s, /* relative= */ true, s->timeout_usec);
if (r < 0)
return r;
@ -770,13 +746,17 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
/* main_pid= */ NULL,
&s->control_pid,
/* main_pid_alien= */ false);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
goto fail;
}
if (r > 0) {
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
r = swap_arm_timer(s, /* relative= */ true, s->timeout_usec);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to install timer: %m");
goto fail;
}
swap_set_state(s, state);
} else if (state == SWAP_DEACTIVATING_SIGTERM && s->kill_context.send_sigkill)
@ -787,7 +767,6 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
@ -817,38 +796,45 @@ static void swap_enter_activating(Swap *s) {
else
r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority);
if (r < 0) {
r = -ENOMEM;
r = log_oom();
goto fail;
}
}
}
r = exec_command_set(s->control_command, "/sbin/swapon", "--fixpgsz", NULL);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to initialize swapon command line: %m");
goto fail;
}
if (s->parameters_fragment.options || opts) {
r = exec_command_append(s->control_command, "-o",
opts ?: s->parameters_fragment.options, NULL);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to prepare swapon command line: %m");
goto fail;
}
}
r = exec_command_append(s->control_command, s->what, NULL);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to prepare swapon command line: %m");
goto fail;
}
swap_unwatch_control_pid(s);
r = swap_spawn(s, s->control_command, &s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'swapon' task: %m");
goto fail;
}
swap_set_state(s, SWAP_ACTIVATING);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapon' task: %m");
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
@ -864,21 +850,23 @@ static void swap_enter_deactivating(Swap *s) {
"/sbin/swapoff",
s->what,
NULL);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to prepare swapoff command line: %m");
goto fail;
}
swap_unwatch_control_pid(s);
r = swap_spawn(s, s->control_command, &s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to spawn 'swapoff' task: %m");
goto fail;
}
swap_set_state(s, SWAP_DEACTIVATING);
return;
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run 'swapoff' task: %m");
swap_enter_dead_or_active(s, SWAP_FAILURE_RESOURCES);
}
@ -1179,7 +1167,7 @@ static int swap_load_proc_swaps(Manager *m, bool set_flags) {
if (k == EOF)
break;
log_warning("Failed to parse /proc/swaps:%u.", i);
log_warning("Failed to parse /proc/swaps:%u, skipping.", i);
continue;
}
@ -1202,8 +1190,6 @@ static int swap_process_proc_swaps(Manager *m) {
r = swap_load_proc_swaps(m, true);
if (r < 0) {
log_error_errno(r, "Failed to reread /proc/swaps: %m");
/* Reset flags, just in case, for late calls */
LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_SWAP]) {
Swap *swap = SWAP(u);
@ -1539,19 +1525,22 @@ static int swap_clean(Unit *u, ExecCleanMask mask) {
s->control_command = NULL;
s->control_command_id = _SWAP_EXEC_COMMAND_INVALID;
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec));
if (r < 0)
r = swap_arm_timer(s, /* relative= */ true, s->exec_context.timeout_clean_usec);
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to install timer: %m");
goto fail;
}
r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(u, r, "Failed to spawn cleaning task: %m");
goto fail;
}
swap_set_state(s, SWAP_CLEANING);
return 0;
fail:
log_unit_warning_errno(u, r, "Failed to initiate cleaning: %m");
s->clean_result = SWAP_FAILURE_RESOURCES;
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
return r;

View file

@ -379,8 +379,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
trigger = UNIT_TRIGGER(UNIT(t));
if (!trigger) {
log_unit_error(UNIT(t), "Unit to trigger vanished.");
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
return;
goto fail;
}
triple_timestamp_get(&ts);
@ -505,12 +504,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
if (t->monotonic_event_source) {
r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to reschedule monotonic event source: %m");
goto fail;
}
r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to enable monotonic event source: %m");
goto fail;
}
} else {
r = sd_event_add_time(
@ -519,8 +522,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
timer_dispatch, t);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to add monotonic event source: %m");
goto fail;
}
(void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic");
}
@ -528,8 +533,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
} else if (t->monotonic_event_source) {
r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to disable monotonic event source: %m");
goto fail;
}
}
if (found_realtime) {
@ -539,12 +546,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
if (t->realtime_event_source) {
r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to reschedule realtime event source: %m");
goto fail;
}
r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to enable realtime event source: %m");
goto fail;
}
} else {
r = sd_event_add_time(
UNIT(t)->manager->event,
@ -552,8 +563,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
t->next_elapse_realtime, t->accuracy_usec,
timer_dispatch, t);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to add realtime event source: %m");
goto fail;
}
(void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime");
}
@ -561,15 +574,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
} else if (t->realtime_event_source) {
r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
if (r < 0)
if (r < 0) {
log_unit_warning_errno(UNIT(t), r, "Failed to disable realtime event source: %m");
goto fail;
}
}
timer_set_state(t, TIMER_WAITING);
return;
fail:
log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m");
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
}
@ -589,19 +603,20 @@ static void timer_enter_running(Timer *t) {
trigger = UNIT_TRIGGER(UNIT(t));
if (!trigger) {
log_unit_error(UNIT(t), "Unit to trigger vanished.");
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
return;
goto fail;
}
details = activation_details_new(UNIT(t));
if (!details) {
r = -ENOMEM;
log_oom();
goto fail;
}
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, &job);
if (r < 0)
if (r < 0) {
log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
goto fail;
}
dual_timestamp_get(&t->last_trigger);
ACTIVATION_DETAILS_TIMER(details)->last_trigger = t->last_trigger;
@ -615,7 +630,6 @@ static void timer_enter_running(Timer *t) {
return;
fail:
log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
}

View file

@ -6276,6 +6276,49 @@ int unit_get_transitive_dependency_set(Unit *u, UnitDependencyAtom atom, Set **r
return 0;
}
int unit_arm_timer(
Unit *u,
sd_event_source **source,
bool relative,
usec_t usec,
sd_event_time_handler_t handler) {
int r;
assert(u);
assert(source);
assert(handler);
if (*source) {
if (usec == USEC_INFINITY)
return sd_event_source_set_enabled(*source, SD_EVENT_OFF);
r = (relative ? sd_event_source_set_time_relative : sd_event_source_set_time)(*source, usec);
if (r < 0)
return r;
return sd_event_source_set_enabled(*source, SD_EVENT_ONESHOT);
}
if (usec == USEC_INFINITY)
return 0;
r = (relative ? sd_event_add_time_relative : sd_event_add_time)(
u->manager->event,
source,
CLOCK_MONOTONIC,
usec, 0,
handler,
u);
if (r < 0)
return r;
const char *d = strjoina(unit_type_to_string(u->type), "-timer");
(void) sd_event_source_set_description(*source, d);
return 0;
}
const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX] = {
[UNIT_PATH] = &activation_details_path_vtable,
[UNIT_TIMER] = &activation_details_timer_vtable,

View file

@ -1090,6 +1090,8 @@ int unit_thaw_vtable_common(Unit *u);
Condition *unit_find_failed_condition(Unit *u);
int unit_arm_timer(Unit *u, sd_event_source **source, bool relative, usec_t usec, sd_event_time_handler_t handler);
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full_errno_zerook(unit, level, error, ...) \