Blob Blame History Raw
From 79b4165b8468d2e753f6ce36ce5589f44be85691 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Wed, 26 Nov 2014 16:33:43 +0100
Subject: [PATCH] core: fix assertion failure in checking a transaction with a
 JOB_NOP

Several functions called from transaction_activate() need to correctly
handle the case where a JOB_NOP job is being checked against a unit's
pending job. The assumption that JOB_NOP never merges with other job
types was correct, but since the job_type_is_*() functions are
implemented using the merge lookup, they need to special-case JOB_NOP
to avoid hitting assertion failures.

(cherry picked from commit 7e803f5ecf689216d6fcd8a1d19a442f234bf28b)
---
 src/core/job.c |  3 +++
 src/core/job.h | 14 ++++++++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/core/job.c b/src/core/job.c
index eaa4bb17fc..db44fee32a 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -352,6 +352,9 @@ bool job_type_is_redundant(JobType a, UnitActiveState b) {
                 return
                         b == UNIT_ACTIVATING;
 
+        case JOB_NOP:
+                return true;
+
         default:
                 assert_not_reached("Invalid job type");
         }
diff --git a/src/core/job.h b/src/core/job.h
index 1e7c61b04f..ee8e54a806 100644
--- a/src/core/job.h
+++ b/src/core/job.h
@@ -49,9 +49,11 @@ enum JobType {
         _JOB_TYPE_MAX_MERGING,
 
         /* JOB_NOP can enter into a transaction, but as it won't pull in
-         * any dependencies, it won't have to merge with anything.
-         * job_install() avoids the problem of merging JOB_NOP too (it's
-         * special-cased, only merges with other JOB_NOPs). */
+         * any dependencies and it uses the special 'nop_job' slot in Unit,
+         * it won't have to merge with anything (except possibly into another
+         * JOB_NOP, previously installed). JOB_NOP is special-cased in
+         * job_type_is_*() functions so that the transaction can be
+         * activated. */
         JOB_NOP = _JOB_TYPE_MAX_MERGING, /* do nothing */
 
         _JOB_TYPE_MAX_IN_TRANSACTION,
@@ -190,11 +192,15 @@ _pure_ static inline bool job_type_is_mergeable(JobType a, JobType b) {
 }
 
 _pure_ static inline bool job_type_is_conflicting(JobType a, JobType b) {
-        return !job_type_is_mergeable(a, b);
+        return a != JOB_NOP && b != JOB_NOP && !job_type_is_mergeable(a, b);
 }
 
 _pure_ static inline bool job_type_is_superset(JobType a, JobType b) {
         /* Checks whether operation a is a "superset" of b in its actions */
+        if (b == JOB_NOP)
+                return true;
+        if (a == JOB_NOP)
+                return false;
         return a == job_type_lookup_merge(a, b);
 }