core: don't choke if a unit another unit triggers vanishes during reload

Fixes: #1981
This commit is contained in:
Lennart Poettering 2016-02-10 23:39:31 +01:00
parent 03a7868805
commit e903182e5b
3 changed files with 62 additions and 9 deletions

View file

@ -726,7 +726,15 @@ static void automount_enter_runnning(Automount *a) {
if (!S_ISDIR(st.st_mode) || st.st_dev != a->dev_id)
log_unit_info(UNIT(a), "Automount point already active?");
else {
r = manager_add_job(UNIT(a)->manager, JOB_START, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
Unit *trigger;
trigger = UNIT_TRIGGER(UNIT(a));
if (!trigger) {
log_unit_error(UNIT(a), "Unit to trigger vanished.");
goto fail;
}
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
goto fail;
@ -742,6 +750,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);
@ -751,8 +760,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, "Refusing to start, unit to trigger not loaded.");
return -ENOENT;
}
a->result = AUTOMOUNT_SUCCESS;
automount_enter_waiting(a);
@ -899,6 +911,7 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
union autofs_v5_packet_union packet;
Automount *a = AUTOMOUNT(userdata);
struct stat st;
Unit *trigger;
int r;
assert(a);
@ -971,7 +984,13 @@ static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, vo
break;
}
r = manager_add_job(UNIT(a)->manager, JOB_STOP, UNIT_TRIGGER(UNIT(a)), JOB_REPLACE, &error, NULL);
trigger = UNIT_TRIGGER(UNIT(a));
if (!trigger) {
log_unit_error(UNIT(a), "Unit to trigger vanished.");
goto fail;
}
r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
goto fail;

View file

@ -464,6 +464,7 @@ static void path_enter_dead(Path *p, PathResult f) {
static void path_enter_running(Path *p) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *trigger;
int r;
assert(p);
@ -472,7 +473,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, &error, NULL);
trigger = UNIT_TRIGGER(UNIT(p));
if (!trigger) {
log_unit_error(UNIT(p), "Unit to trigger vanished.");
path_enter_dead(p, TIMER_FAILURE_RESOURCES);
return;
}
r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
@ -553,12 +561,16 @@ 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, "Refusing to start, unit to trigger not loaded.");
return -ENOENT;
}
path_mkdir(p);

View file

@ -357,8 +357,18 @@ static void timer_enter_waiting(Timer *t, bool initial) {
usec_t base = 0;
bool leave_around = false;
TimerValue *v;
Unit *trigger;
int r;
assert(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;
}
/* If we shall wake the system we use the boottime clock
* rather than the monotonic clock. */
@ -417,7 +427,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
case TIMER_UNIT_ACTIVE:
leave_around = true;
base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
base = trigger->inactive_exit_timestamp.monotonic;
if (base <= 0)
base = t->last_trigger.monotonic;
@ -429,7 +439,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
case TIMER_UNIT_INACTIVE:
leave_around = true;
base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
base = trigger->inactive_enter_timestamp.monotonic;
if (base <= 0)
base = t->last_trigger.monotonic;
@ -552,6 +562,7 @@ fail:
static void timer_enter_running(Timer *t) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
Unit *trigger;
int r;
assert(t);
@ -560,7 +571,14 @@ 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, &error, NULL);
trigger = UNIT_TRIGGER(UNIT(t));
if (!trigger) {
log_unit_error(UNIT(t), "Unit to trigger vanished.");
timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
return;
}
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
if (r < 0)
goto fail;
@ -580,12 +598,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, "Refusing to start, unit to trigger not loaded.");
return -ENOENT;
}
t->last_trigger = DUAL_TIMESTAMP_NULL;