job: Ensure JobRunningTimeoutSec= survives serialization (#6128)
This is a fixup of commit a2df3ea4ae
.
When there is a running job with JobRunningTimeoutSec= and systemd serializes
its state (e.g. during daemon-reload), the timer event source won't be properly
restored in job_coldplug().
Thus save and serialize begin_running_usec too and reinitialize the timer based
on that value.
This commit is contained in:
parent
f7b1c8d1fc
commit
171f12ced8
|
@ -952,14 +952,15 @@ static int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *user
|
|||
|
||||
int job_start_timer(Job *j, bool job_running) {
|
||||
int r;
|
||||
usec_t run_begin, timeout_time, old_timeout_time;
|
||||
usec_t timeout_time, old_timeout_time;
|
||||
|
||||
if (job_running) {
|
||||
j->begin_running_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (j->unit->job_running_timeout == USEC_INFINITY)
|
||||
return 0;
|
||||
|
||||
run_begin = now(CLOCK_MONOTONIC);
|
||||
timeout_time = usec_add(run_begin, j->unit->job_running_timeout);
|
||||
timeout_time = usec_add(j->begin_running_usec, j->unit->job_running_timeout);
|
||||
|
||||
if (j->timer_event_source) {
|
||||
/* Update only if JobRunningTimeoutSec= results in earlier timeout */
|
||||
|
@ -1051,6 +1052,8 @@ int job_serialize(Job *j, FILE *f) {
|
|||
|
||||
if (j->begin_usec > 0)
|
||||
fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
|
||||
if (j->begin_running_usec > 0)
|
||||
fprintf(f, "job-begin-running="USEC_FMT"\n", j->begin_running_usec);
|
||||
|
||||
bus_track_serialize(j->bus_track, f, "subscribed");
|
||||
|
||||
|
@ -1148,6 +1151,14 @@ int job_deserialize(Job *j, FILE *f) {
|
|||
else
|
||||
j->begin_usec = ull;
|
||||
|
||||
} else if (streq(l, "job-begin-running")) {
|
||||
unsigned long long ull;
|
||||
|
||||
if (sscanf(v, "%llu", &ull) != 1)
|
||||
log_debug("Failed to parse job-begin-running value %s", v);
|
||||
else
|
||||
j->begin_running_usec = ull;
|
||||
|
||||
} else if (streq(l, "subscribed")) {
|
||||
|
||||
if (strv_extend(&j->deserialized_clients, v) < 0)
|
||||
|
@ -1158,6 +1169,7 @@ int job_deserialize(Job *j, FILE *f) {
|
|||
|
||||
int job_coldplug(Job *j) {
|
||||
int r;
|
||||
usec_t timeout_time = USEC_INFINITY;
|
||||
|
||||
assert(j);
|
||||
|
||||
|
@ -1171,7 +1183,18 @@ int job_coldplug(Job *j) {
|
|||
/* Maybe due to new dependencies we don't actually need this job anymore? */
|
||||
job_add_to_gc_queue(j);
|
||||
|
||||
if (j->begin_usec == 0 || j->unit->job_timeout == USEC_INFINITY)
|
||||
/* Create timer only when job began or began running and the respective timeout is finite.
|
||||
* Follow logic of job_start_timer() if both timeouts are finite */
|
||||
if (j->begin_usec == 0)
|
||||
return 0;
|
||||
|
||||
if (j->unit->job_timeout != USEC_INFINITY)
|
||||
timeout_time = usec_add(j->begin_usec, j->unit->job_timeout);
|
||||
|
||||
if (j->begin_running_usec > 0 && j->unit->job_running_timeout != USEC_INFINITY)
|
||||
timeout_time = MIN(timeout_time, usec_add(j->begin_running_usec, j->unit->job_running_timeout));
|
||||
|
||||
if (timeout_time == USEC_INFINITY)
|
||||
return 0;
|
||||
|
||||
j->timer_event_source = sd_event_source_unref(j->timer_event_source);
|
||||
|
@ -1180,7 +1203,7 @@ int job_coldplug(Job *j) {
|
|||
j->manager->event,
|
||||
&j->timer_event_source,
|
||||
CLOCK_MONOTONIC,
|
||||
usec_add(j->begin_usec, j->unit->job_timeout), 0,
|
||||
timeout_time, 0,
|
||||
job_dispatch_timer, j);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to restart timeout for job: %m");
|
||||
|
|
|
@ -150,6 +150,7 @@ struct Job {
|
|||
|
||||
sd_event_source *timer_event_source;
|
||||
usec_t begin_usec;
|
||||
usec_t begin_running_usec;
|
||||
|
||||
/*
|
||||
* This tracks where to send signals, and also which clients
|
||||
|
|
Loading…
Reference in a new issue