diff --git a/src/core/transaction.c b/src/core/transaction.c index 5fa21e080b..0f7fe451e7 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -15,6 +15,7 @@ #include "strv.h" #include "transaction.h" +static bool job_matters_to_anchor(Job *job); static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies); static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependencies) { @@ -171,6 +172,7 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *job) { * another unit in which case we * rather remove the start. */ + /* Update test/units/TEST-87-AUX-UTILS-VM.sh when logs below are changed. */ log_unit_debug(j->unit, "Looking at job %s/%s conflicted_by=%s", j->unit->id, job_type_to_string(j->type), @@ -216,17 +218,18 @@ static int delete_one_unmergeable_job(Transaction *tr, Job *job) { return -EINVAL; } -static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { +static int transaction_ensure_mergeable(Transaction *tr, bool matters_to_anchor, sd_bus_error *e) { Job *j; int r; assert(tr); - /* First step, check whether any of the jobs for one specific - * task conflict. If so, try to drop one of them. */ HASHMAP_FOREACH(j, tr->jobs) { JobType t; + if (job_matters_to_anchor(j) != matters_to_anchor) + continue; + t = j->type; LIST_FOREACH(transaction, k, j->transaction_next) { if (job_type_merge_and_collapse(&t, k->type, j->unit) >= 0) @@ -253,7 +256,26 @@ static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { } } - /* Second step, merge the jobs. */ + return 0; +} + +static int transaction_merge_jobs(Transaction *tr, sd_bus_error *e) { + Job *j; + int r; + + assert(tr); + + /* First step, try to drop unmergeable jobs for jobs that matter to anchor. */ + r = transaction_ensure_mergeable(tr, /* matters_to_anchor = */ true, e); + if (r < 0) + return r; + + /* Second step, do the same for jobs that not matter to anchor. */ + r = transaction_ensure_mergeable(tr, /* matters_to_anchor = */ false, e); + if (r < 0) + return r; + + /* Third step, merge the jobs. */ HASHMAP_FOREACH(j, tr->jobs) { JobType t = j->type; diff --git a/test/units/TEST-87-AUX-UTILS-VM.sh b/test/units/TEST-87-AUX-UTILS-VM.sh index 9c2a033aa9..ecbff290f0 100755 --- a/test/units/TEST-87-AUX-UTILS-VM.sh +++ b/test/units/TEST-87-AUX-UTILS-VM.sh @@ -3,6 +3,14 @@ set -eux set -o pipefail +# For issue #38765 +journalctl --sync +if journalctl -q -o short-monotonic --grep "Looking at job .*/.* conflicted_by=(yes|no)" >/failed; then + echo "Found unexpected unmergeable jobs" + cat /failed + exit 1 +fi + # shellcheck source=test/units/test-control.sh . "$(dirname "$0")"/test-control.sh