[systemd-commits] 4 commits - src/core test/TEST-03-JOBS

Michal Schmidt michich at kemper.freedesktop.org
Wed Nov 26 07:35:30 PST 2014


 src/core/job.c                 |    7 +++++--
 src/core/job.h                 |   14 ++++++++++----
 src/core/transaction.c         |    2 +-
 test/TEST-03-JOBS/test-jobs.sh |    9 +++++++++
 4 files changed, 25 insertions(+), 7 deletions(-)

New commits:
commit e0312f4db08c7100bd00299614e87bedc759b366
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Wed Nov 26 16:33:46 2014 +0100

    core: fix check for transaction destructiveness
    
    When checking if the transaction is destructive, we need to check if the
    previously installed job is a superset of the new job (and hence the new
    job will fold into the installed one without changing it), not the other
    way around.

diff --git a/src/core/transaction.c b/src/core/transaction.c
index bbaa6da..b992edd 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -511,7 +511,7 @@ static int transaction_is_destructive(Transaction *tr, JobMode mode, sd_bus_erro
                 assert(!j->transaction_next);
 
                 if (j->unit->job && (mode == JOB_FAIL || j->unit->job->irreversible) &&
-                    !job_type_is_superset(j->type, j->unit->job->type))
+                    !job_type_is_superset(j->unit->job->type, j->type))
                         return sd_bus_error_setf(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE,
                                                  "Transaction is destructive.");
         }

commit 61da906a744594002c2c967ecf6ec7899c7a9397
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Wed Nov 26 16:33:45 2014 +0100

    core: drop now-redundant special-casing of JOB_NOP
    
    job_type_is_conflicting(X, JOB_NOP) correctly gives: false.
    
    job_type_allows_late_merge(JOB_NOP) && job_type_is_superset(X, JOB_NOP)
    correctly gives: true.

diff --git a/src/core/job.c b/src/core/job.c
index 1411603..9adc3fd 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -160,12 +160,12 @@ Job* job_install(Job *j) {
         uj = *pj;
 
         if (uj) {
-                if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
+                if (job_type_is_conflicting(uj->type, j->type))
                         job_finish_and_invalidate(uj, JOB_CANCELED, false);
                 else {
                         /* not conflicting, i.e. mergeable */
 
-                        if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
+                        if (uj->state == JOB_WAITING ||
                             (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
                                 job_merge_into_installed(uj, j);
                                 log_debug_unit(uj->unit->id,

commit 7e803f5ecf689216d6fcd8a1d19a442f234bf28b
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Wed Nov 26 16:33:43 2014 +0100

    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.

diff --git a/src/core/job.c b/src/core/job.c
index 51d1581..1411603 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 b7ebd8d..223ff9c 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,
@@ -191,11 +193,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);
 }
 

commit 06c1c4f98c0d0b4c93e58d75ed5a08d722ec4de3
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Wed Nov 26 16:33:40 2014 +0100

    test: add test for crash when adding a JOB_NOP

diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh
index 12b38af..28368b7 100755
--- a/test/TEST-03-JOBS/test-jobs.sh
+++ b/test/TEST-03-JOBS/test-jobs.sh
@@ -21,6 +21,15 @@ ELAPSED=$(($END_SEC-$START_SEC))
 systemctl list-jobs > /root/list-jobs.txt
 grep 'sleep\.service.*running' /root/list-jobs.txt || exit 1
 grep 'hello\.service' /root/list-jobs.txt && exit 1
+systemctl stop sleep.service hello-after-sleep.target || exit 1
+
+# Test for a crash when enqueueing a JOB_NOP when other job already exists
+systemctl start --no-block hello-after-sleep.target || exit 1
+# hello.service should still be waiting, so these try-restarts will collapse
+# into NOPs.
+systemctl try-restart --fail hello.service || exit 1
+systemctl try-restart hello.service || exit 1
+systemctl stop hello.service sleep.service hello-after-sleep.target || exit 1
 
 # TODO: add more job queueing/merging tests here.
 



More information about the systemd-commits mailing list