From d7b2f6efd02375af4cf043ef9db6d316b65d4779 Mon Sep 17 00:00:00 2001 From: Jan Synacek Date: Fri, 16 Feb 2018 09:56:50 +0100 Subject: [PATCH] core: don't choke if a unit another unit triggers vanishes during reload Fixes: #1981 (cherry picked from e903182e5b0daa941de47a9c08c824106cec7fe0) Resolves: #1545676 --- src/core/automount.c | 25 +++++++++++++++++++++---- src/core/path.c | 18 +++++++++++++++--- src/core/timer.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/core/automount.c b/src/core/automount.c index 182ba5240..679fe071e 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -715,6 +715,7 @@ static int automount_start_expire(Automount *a) { static void automount_enter_running(Automount *a) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; struct stat st; + Unit *trigger; int r; assert(a); @@ -753,8 +754,13 @@ static void automount_enter_running(Automount *a) { return; } - r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)), - JOB_REPLACE, true, &error, NULL); + trigger = UNIT_TRIGGER(UNIT(a)); + if (!trigger) { + log_unit_error(UNIT(a)->id, "Unit to trigger vanished."); + goto fail; + } + + r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL); if (r < 0) { log_unit_warning(UNIT(a)->id, "%s failed to queue mount startup job: %s", @@ -775,6 +781,7 @@ fail: static int automount_start(Unit *u) { Automount *a = AUTOMOUNT(u); + Unit *trigger; assert(a); assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); @@ -786,8 +793,11 @@ static int automount_start(Unit *u) { return -EEXIST; } - if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED) + trigger = UNIT_TRIGGER(u); + if (!trigger || trigger->load_state != UNIT_LOADED) { + log_unit_error(u->id, "Refusing to start, unit to trigger not loaded."); return -ENOENT; + } a->result = AUTOMOUNT_SUCCESS; automount_enter_waiting(a); @@ -936,6 +946,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; union autofs_v5_packet_union packet; Automount *a = AUTOMOUNT(userdata); + Unit *trigger; ssize_t l; int r; @@ -1002,7 +1013,13 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo log_unit_error_errno(UNIT(a)->id, r, "Failed to remember token: %m"); goto fail; } - r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, true, &error, NULL); + + trigger = UNIT_TRIGGER(UNIT(a)); + if (!trigger) { + log_unit_error(UNIT(a)->id, "Unit to trigger vanished."); + goto fail; + } + r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, true, &error, NULL); if (r < 0) { log_unit_warning(UNIT(a)->id, "%s failed to queue umount startup job: %s", diff --git a/src/core/path.c b/src/core/path.c index 51e36fa8b..0533bb4e2 100644 --- a/src/core/path.c +++ b/src/core/path.c @@ -475,6 +475,7 @@ static void path_enter_dead(Path *p, PathResult f) { static void path_enter_running(Path *p) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *trigger; int r; assert(p); @@ -483,8 +484,14 @@ static void path_enter_running(Path *p) { if (unit_stop_pending(UNIT(p))) return; - r = manager_add_job(UNIT(p)->manager, JOB_START, UNIT_TRIGGER(UNIT(p)), - JOB_REPLACE, true, &error, NULL); + trigger = UNIT_TRIGGER(UNIT(p)); + if (!trigger) { + log_unit_error(UNIT(p)->id, "Unit to trigger vanished."); + path_enter_dead(p, TIMER_FAILURE_RESOURCES); + return; + } + + r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL); if (r < 0) goto fail; @@ -566,12 +573,17 @@ static void path_mkdir(Path *p) { static int path_start(Unit *u) { Path *p = PATH(u); + Unit *trigger; assert(p); assert(p->state == PATH_DEAD || p->state == PATH_FAILED); - if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED) + + trigger = UNIT_TRIGGER(u); + if (!trigger || trigger->load_state != UNIT_LOADED) { + log_unit_error(u->id, "Refusing to start, unit to trigger not loaded."); return -ENOENT; + } path_mkdir(p); diff --git a/src/core/timer.c b/src/core/timer.c index f318dc6f4..91d8db67e 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -343,8 +343,18 @@ static void timer_enter_waiting(Timer *t, bool initial) { usec_t ts_realtime, ts_monotonic; usec_t base = 0; TimerValue *v; + Unit *trigger; int r; + assert(t); + + trigger = UNIT_TRIGGER(UNIT(t)); + if (!trigger) { + log_unit_error(UNIT(t)->id, "Unit to trigger vanished."); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); + return; + } + /* If we shall wake the system we use the boottime clock * rather than the monotonic clock. */ @@ -399,7 +409,7 @@ static void timer_enter_waiting(Timer *t, bool initial) { case TIMER_UNIT_ACTIVE: - base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic; + base = trigger->inactive_exit_timestamp.monotonic; if (base <= 0) base = t->last_trigger.monotonic; @@ -523,6 +533,7 @@ fail: static void timer_enter_running(Timer *t) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + Unit *trigger; int r; assert(t); @@ -531,8 +542,15 @@ static void timer_enter_running(Timer *t) { if (unit_stop_pending(UNIT(t))) return; - r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)), - JOB_REPLACE, true, &error, NULL); + + trigger = UNIT_TRIGGER(UNIT(t)); + if (!trigger) { + log_unit_error(UNIT(t)->id, "Unit to trigger vanished."); + timer_enter_dead(t, TIMER_FAILURE_RESOURCES); + return; + } + + r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, true, &error, NULL); if (r < 0) goto fail; @@ -554,12 +572,16 @@ fail: static int timer_start(Unit *u) { Timer *t = TIMER(u); TimerValue *v; + Unit *trigger; assert(t); assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED); - if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED) + trigger = UNIT_TRIGGER(u); + if (!trigger || trigger->load_state != UNIT_LOADED) { + log_unit_error(u->id, "Refusing to start, unit to trigger not loaded."); return -ENOENT; + } t->last_trigger = DUAL_TIMESTAMP_NULL;