j->manager = unit->manager;
j->unit = unit;
j->type = _JOB_TYPE_INVALID;
+ j->reloaded = false;
return j;
}
return j;
}
-void job_free(Job *j) {
+void job_unlink(Job *j) {
assert(j);
assert(!j->installed);
assert(!j->transaction_prev);
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;
+ }
- if (j->in_gc_queue)
+ if (j->in_gc_queue) {
LIST_REMOVE(gc_queue, j->manager->gc_job_queue, j);
+ j->in_gc_queue = false;
+ }
- sd_event_source_unref(j->timer_event_source);
+ 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->bus_track);
strv_free(j->deserialized_clients);
*pj = j;
j->installed = true;
+ j->reloaded = true;
if (j->state == JOB_RUNNING)
j->unit->manager->n_running_jobs++;
}
}
+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, bool already) {
Unit *u;
Unit *other;
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) {
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;
if (q < 0 && r >= 0)
r = q;
+ if (!MANAGER_IS_RELOADING(m))
+ manager_flush_finished_jobs(m);
+
m->send_reloading_done = true;
return r;