]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: refuse late merge only for anchor job when JOB_RESTART_DEPENDENCIES
authorMike Yuan <me@yhndnzj.com>
Sat, 8 Jul 2023 11:45:51 +0000 (19:45 +0800)
committerLennart Poettering <lennart@poettering.net>
Wed, 12 Jul 2023 16:25:45 +0000 (18:25 +0200)
Follow-up for 2a39b91459a4c27985d9a58309c0fda25f3cd397

The mentioned change makes all jobs in the transaction unmergeable
if mode == JOB_RESTART_DEPENDENCIES, but we only want the anchor job
to be re-enqueued.

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

index 95e71c48e23e6fb4150c4e61978978a820815d2b..acf8a78f41363bc1fdfc719739ca76c7b1688909 100644 (file)
@@ -217,10 +217,11 @@ static void job_merge_into_installed(Job *j, Job *other) {
         j->ignore_order = j->ignore_order || other->ignore_order;
 }
 
-Job* job_install(Job *j, JobMode mode) {
+Job* job_install(Job *j, bool refuse_late_merge) {
         Job **pj;
         Job *uj;
 
+        assert(j);
         assert(!j->installed);
         assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
         assert(j->state == JOB_WAITING);
@@ -235,7 +236,7 @@ Job* job_install(Job *j, JobMode mode) {
                         /* not conflicting, i.e. mergeable */
 
                         if (uj->state == JOB_WAITING ||
-                            (job_type_allows_late_merge(j->type) && mode != JOB_RESTART_DEPENDENCIES && job_type_is_superset(uj->type, j->type))) {
+                            (!refuse_late_merge && job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
                                 job_merge_into_installed(uj, j);
                                 log_unit_debug(uj->unit,
                                                "Merged %s/%s into installed job %s/%s as %"PRIu32,
index 2c4fbdf4eda0a2c1c967cbbe99d8f29def70806c..891d87a79cd558426b7eabf1d74754579b9e0372 100644 (file)
@@ -169,7 +169,7 @@ Job* job_new(Unit *unit, JobType type);
 Job* job_new_raw(Unit *unit);
 void job_unlink(Job *job);
 Job* job_free(Job *job);
-Job* job_install(Job *j, JobMode mode);
+Job* job_install(Job *j, bool refuse_late_merge);
 int job_install_deserialized(Job *j);
 void job_uninstall(Job *j);
 void job_dump(Job *j, FILE *f, const char *prefix);
index 8b8e02f1c77d9426f3dd73b7687a688aea92627e..ffc063a6842106cf7dcc58dd9379f546f228d71a 100644 (file)
@@ -657,14 +657,19 @@ static int transaction_apply(
                 /* Clean the job dependencies */
                 transaction_unlink_job(tr, j, false);
 
-                installed_job = job_install(j, mode);
+                /* When RestartMode=direct is used, the service being restarted don't enter the inactive/failed
+                 * state, i.e. unit_process_job -> job_finish_and_invalidate is never called, and the previous
+                 * job might still be running (especially for Type=oneshot services). We need to refuse
+                 * late merge and re-enqueue the anchor job. */
+                installed_job = job_install(j,
+                                            /* refuse_late_merge = */ mode == JOB_RESTART_DEPENDENCIES && j == tr->anchor_job);
                 if (installed_job != j) {
                         /* j has been merged into a previously installed job */
                         if (tr->anchor_job == j)
                                 tr->anchor_job = installed_job;
+
                         hashmap_remove_value(m->jobs, UINT32_TO_PTR(j->id), j);
-                        job_free(j);
-                        j = installed_job;
+                        free_and_replace_full(j, installed_job, job_free);
                 }
 
                 job_add_to_run_queue(j);