unit_add_to_gc_queue(j->unit);
+ unit_add_to_dbus_queue(j->unit); /* The Job property of the unit has changed now */
+
hashmap_remove_value(j->manager->jobs, UINT32_TO_PTR(j->id), j);
j->installed = false;
}
job_fail_dependencies(u, UNIT_CONFLICTED_BY);
}
+ /* A special check to make sure we take down anything RequisiteOf if we
+ * aren't active. This is when the verify-active job merges with a
+ * satisfying job type, and then loses it's invalidation effect, as the
+ * result there is JOB_DONE for the start job we merged into, while we
+ * should be failing the depending job if the said unit isn't infact
+ * active. Oneshots are an example of this, where going directly from
+ * activating to inactive is success.
+ *
+ * This happens when you use ConditionXYZ= in a unit too, since in that
+ * case the job completes with the JOB_DONE result, but the unit never
+ * really becomes active. Note that such a case still involves merging:
+ *
+ * A start job waits for something else, and a verify-active comes in
+ * and merges in the installed job. Then, later, when it becomes
+ * runnable, it finishes with JOB_DONE result as execution on conditions
+ * not being met is skipped, breaking our dependency semantics.
+ *
+ * Also, depending on if start job waits or not, the merging may or may
+ * not happen (the verify-active job may trigger after it finishes), so
+ * you get undeterministic results without this check.
+ */
+ if (result == JOB_DONE && recursive && !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
+ if (IN_SET(t, JOB_START, JOB_RELOAD))
+ job_fail_dependencies(u, UNIT_REQUISITE_OF);
+ }
/* Trigger OnFailure dependencies that are not generated by
* the unit itself. We don't treat JOB_CANCELED as failure in
* this context. And JOB_FAILURE is already handled by the