You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.6 KiB
212 lines
7.6 KiB
From d7b2f6efd02375af4cf043ef9db6d316b65d4779 Mon Sep 17 00:00:00 2001 |
|
From: Jan Synacek <jsynacek@redhat.com> |
|
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 182ba5240f..679fe071e7 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 51e36fa8be..0533bb4e21 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 f318dc6f44..91d8db67e8 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; |
|
|
|
|