Skip to content

Commit 791cd15

Browse files
bl33pbl0ppoettering
authored andcommitted
Fail RequisiteOf units with oneshots
Fixes: #11422 Oneshots going to inactive directly without ever entering UNIT_ACTIVE is considered success. This however means that if something both Requires= and Requisites= a unit of such nature, the verify-active job getting merged into the start job makes it lose this property of failing the depending jobs, as there, the start job has the result JOB_DONE on success, so we never walk over RequisiteOf units. This change makes sure that such units always go down. It is also only meaningful with After=, but so is Requisite= itself. Also, we also catch cases like a oneshot having RemainAfterExit= true making us start up properly in such a setting, but then removing it, reloading the unit, and restarting it. In such a case, we go down due to restart propagation before them, and our start job waits on theirs, properly failing with the JOB_DEPENDENCY result. This covers cases where ConditionXYZ= creates a similar situation as well.
1 parent a15ff62 commit 791cd15

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

src/core/job.c

+25
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,31 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
10271027
job_fail_dependencies(u, UNIT_CONFLICTED_BY);
10281028
}
10291029

1030+
/* A special check to make sure we take down anything RequisiteOf if we
1031+
* aren't active. This is when the verify-active job merges with a
1032+
* satisfying job type, and then loses it's invalidation effect, as the
1033+
* result there is JOB_DONE for the start job we merged into, while we
1034+
* should be failing the depending job if the said unit isn't infact
1035+
* active. Oneshots are an example of this, where going directly from
1036+
* activating to inactive is success.
1037+
*
1038+
* This happens when you use ConditionXYZ= in a unit too, since in that
1039+
* case the job completes with the JOB_DONE result, but the unit never
1040+
* really becomes active. Note that such a case still involves merging:
1041+
*
1042+
* A start job waits for something else, and a verify-active comes in
1043+
* and merges in the installed job. Then, later, when it becomes
1044+
* runnable, it finishes with JOB_DONE result as execution on conditions
1045+
* not being met is skipped, breaking our dependency semantics.
1046+
*
1047+
* Also, depending on if start job waits or not, the merging may or may
1048+
* not happen (the verify-active job may trigger after it finishes), so
1049+
* you get undeterministic results without this check.
1050+
*/
1051+
if (result == JOB_DONE && recursive && !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
1052+
if (IN_SET(t, JOB_START, JOB_RELOAD))
1053+
job_fail_dependencies(u, UNIT_REQUISITE_OF);
1054+
}
10301055
/* Trigger OnFailure dependencies that are not generated by
10311056
* the unit itself. We don't treat JOB_CANCELED as failure in
10321057
* this context. And JOB_FAILURE is already handled by the

0 commit comments

Comments
 (0)