]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
job: Ensure JobRunningTimeoutSec= survives serialization (#6128)
authorMichal Koutný <Werkov@users.noreply.github.com>
Sun, 18 Jun 2017 15:51:17 +0000 (17:51 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 18 Jun 2017 15:51:17 +0000 (11:51 -0400)
This is a fixup of commit a2df3ea4ae058693bc7bf203d144e8af3c9493d2.
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.

src/core/job.c
src/core/job.h

index 5067006d631dcbc89d4a84ab043f3a1b3d44e9a5..899c011db43c00adc6ea05695fb0978b9fcfb11f 100644 (file)
@@ -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");
index 8b3d38fc6013808462d0cd6975257ddb1490aa1b..b17001889efb37a0573b90d5ebb6df8a07aa74df 100644 (file)
@@ -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