diff -Nru systemd-229/debian/changelog systemd-229/debian/changelog --- systemd-229/debian/changelog 2019-02-28 23:50:50.000000000 +0100 +++ systemd-229/debian/changelog 2019-03-13 14:56:25.000000000 +0100 @@ -1,3 +1,12 @@ +systemd (229-4ubuntu21.18~ppa2) xenial; urgency=medium + + * d/p/fix-race-daemon-reload-8803.patch: + - backport systemd upstream PR#8803 to fix race when doing + systemctl and systemctl daemon-reload at the same time + LP: #1819728 + + -- Michael Vogt Wed, 13 Mar 2019 14:56:25 +0100 + systemd (229-4ubuntu21.17) xenial; urgency=medium [ Victor Tapia ] diff -Nru systemd-229/debian/patches/fix-race-daemon-reload-8803.patch systemd-229/debian/patches/fix-race-daemon-reload-8803.patch --- systemd-229/debian/patches/fix-race-daemon-reload-8803.patch 1970-01-01 01:00:00.000000000 +0100 +++ systemd-229/debian/patches/fix-race-daemon-reload-8803.patch 2019-03-13 14:56:09.000000000 +0100 @@ -0,0 +1,170 @@ +Index: systemd-229/src/core/job.c +=================================================================== +--- systemd-229.orig/src/core/job.c ++++ systemd-229/src/core/job.c +@@ -56,6 +56,7 @@ Job* job_new_raw(Unit *unit) { + j->manager = unit->manager; + j->unit = unit; + j->type = _JOB_TYPE_INVALID; ++ j->reloaded = false; + + return j; + } +@@ -77,7 +78,7 @@ Job* job_new(Unit *unit, JobType type) { + return j; + } + +-void job_free(Job *j) { ++void job_unlink(Job *j) { + assert(j); + assert(!j->installed); + assert(!j->transaction_prev); +@@ -85,14 +86,29 @@ void job_free(Job *j) { + assert(!j->subject_list); + assert(!j->object_list); + +- if (j->in_run_queue) ++ if (j->in_run_queue) { + LIST_REMOVE(run_queue, j->manager->run_queue, j); ++ j->in_run_queue = false; ++ } + +- if (j->in_dbus_queue) ++ if (j->in_dbus_queue) { + LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); ++ j->in_dbus_queue = false; ++ } ++ ++ j->timer_event_source = sd_event_source_unref(j->timer_event_source); ++} + +- sd_event_source_unref(j->timer_event_source); ++void job_free(Job *j) { ++ assert(j); ++ assert(!j->installed); ++ assert(!j->transaction_prev); ++ assert(!j->transaction_next); ++ assert(!j->subject_list); ++ assert(!j->object_list); + ++ job_unlink(j); ++ + sd_bus_track_unref(j->clients); + strv_free(j->deserialized_clients); + +@@ -248,6 +264,7 @@ int job_install_deserialized(Job *j) { + + *pj = j; + j->installed = true; ++ j->reloaded = true; + + if (j->state == JOB_RUNNING) + j->unit->manager->n_running_jobs++; +@@ -832,6 +849,19 @@ static void job_fail_dependencies(Unit * + } + } + ++static int job_save_pending_finished_job(Job *j) { ++ int r; ++ ++ assert(j); ++ ++ r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL); ++ if (r < 0) ++ return r; ++ ++ job_unlink(j); ++ return set_put(j->manager->pending_finished_jobs, j); ++} ++ + int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) { + Unit *u; + Unit *other; +@@ -868,7 +898,12 @@ int job_finish_and_invalidate(Job *j, Jo + j->manager->n_failed_jobs ++; + + job_uninstall(j); +- job_free(j); ++ /* Remember jobs started before the reload */ ++ if (MANAGER_IS_RELOADING(j->manager) && j->reloaded) { ++ if (job_save_pending_finished_job(j) < 0) ++ job_free(j); ++ } else ++ job_free(j); + + /* Fail depending jobs on failure */ + if (result != JOB_DONE && recursive) { +@@ -1258,3 +1293,4 @@ const char* job_type_to_access_method(Jo + else + return "reload"; + } ++ +Index: systemd-229/src/core/job.h +=================================================================== +--- systemd-229.orig/src/core/job.h ++++ systemd-229/src/core/job.h +@@ -168,10 +168,12 @@ struct Job { + bool sent_dbus_new_signal:1; + bool ignore_order:1; + bool irreversible:1; ++ bool reloaded:1; + }; + + Job* job_new(Unit *unit, JobType type); + Job* job_new_raw(Unit *unit); ++void job_unlink(Job *job); + void job_free(Job *job); + Job* job_install(Job *j); + int job_install_deserialized(Job *j); +Index: systemd-229/src/core/manager.c +=================================================================== +--- systemd-229.orig/src/core/manager.c ++++ systemd-229/src/core/manager.c +@@ -2497,6 +2497,17 @@ finish: + return r; + } + ++static void manager_flush_finished_jobs(Manager *m) { ++ Job *j; ++ ++ while ((j = set_steal_first(m->pending_finished_jobs))) { ++ bus_job_send_removed_signal(j); ++ job_free(j); ++ } ++ ++ m->pending_finished_jobs = set_free(m->pending_finished_jobs); ++} ++ + int manager_reload(Manager *m) { + int r, q; + _cleanup_fclose_ FILE *f = NULL; +@@ -2575,6 +2586,9 @@ int manager_reload(Manager *m) { + assert(m->n_reloading > 0); + m->n_reloading--; + ++ if (!MANAGER_IS_RELOADING(m)) ++ manager_flush_finished_jobs(m); ++ + m->send_reloading_done = true; + + return r; +Index: systemd-229/src/core/manager.h +=================================================================== +--- systemd-229.orig/src/core/manager.h ++++ systemd-229/src/core/manager.h +@@ -266,6 +266,9 @@ struct Manager { + + /* non-zero if we are reloading or reexecuting, */ + int n_reloading; ++ /* A set which contains all jobs that started before reload and finished ++ * during it */ ++ Set *pending_finished_jobs; + + unsigned n_installed_jobs; + unsigned n_failed_jobs; +@@ -374,3 +377,5 @@ int manager_update_failed_units(Manager + + const char *manager_state_to_string(ManagerState m) _const_; + ManagerState manager_state_from_string(const char *s) _pure_; ++ ++#define MANAGER_IS_RELOADING(m) ((m)->n_reloading > 0) diff -Nru systemd-229/debian/patches/series systemd-229/debian/patches/series --- systemd-229/debian/patches/series 2019-02-28 23:50:50.000000000 +0100 +++ systemd-229/debian/patches/series 2019-03-13 11:25:56.000000000 +0100 @@ -134,3 +134,4 @@ journal-do-not-remove-multiple-spaces-after-identifi.patch stop-mount-error-propagation.patch fix-egde-case-when-processing-proc-self-mountinfo.patch +fix-race-daemon-reload-8803.patch