]> err.no Git - systemd/commitdiff
transaction: fix detection of cycles involving installed jobs
authorMichal Schmidt <mschmidt@redhat.com>
Sun, 22 Apr 2012 00:09:04 +0000 (02:09 +0200)
committerMichal Schmidt <mschmidt@redhat.com>
Mon, 23 Apr 2012 23:54:14 +0000 (01:54 +0200)
A transaction can be acyclic, but when it's added to installed jobs,
a cycle may result.

transaction_verify_order_one() attempts to detect these cases, but it
fails because the installed jobs often have the exact generation number
that makes them look as if they were walked already.

Fix it by resetting the generation numbers of all installed jobs before
detecting cycles.

An alternative fix could be to add the generation counter to the
Manager and use it instead of starting always from 1 in
transaction_activate(). But I prefer not having to worry about it
wrapping around.

src/core/transaction.c

index 398494778337b76c7163ab0286da105c36a1a60c..394c18135232663b93bd025d17f9d96360308cd7 100644 (file)
@@ -603,6 +603,8 @@ rollback:
 }
 
 int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e) {
+        Iterator i;
+        Job *j;
         int r;
         unsigned generation = 1;
 
@@ -611,6 +613,12 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
         /* This applies the changes recorded in tr->jobs to
          * the actual list of jobs, if possible. */
 
+        /* Reset the generation counter of all installed jobs. The detection of cycles
+         * looks at installed jobs. If they had a non-zero generation from some previous
+         * walk of the graph, the algorithm would break. */
+        HASHMAP_FOREACH(j, m->jobs, i)
+                j->generation = 0;
+
         /* First step: figure out which jobs matter */
         transaction_find_jobs_that_matter_to_anchor(tr->anchor_job, generation++);