diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index c20efe5..c5e84d7 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -590,6 +590,16 @@
+ OnStop=
+
+ Lists one or more
+ units that are activated when this
+ unit enters the
+ 'stop'
+ state.
+
+
+
PropagatesReloadTo=
ReloadPropagatedFrom=
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index 83ee018..347263a 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -840,6 +840,7 @@ const BusProperty bus_unit_properties[] = {
{ "Before", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BEFORE]), true },
{ "After", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_AFTER]), true },
{ "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
+ { "OnStop", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_STOP]), true },
{ "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
{ "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
{ "PropagatesReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), true },
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index ac6785a..b614bb1 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -79,6 +79,7 @@
" \n" \
" \n" \
" \n" \
+ " \n" \
" \n" \
" \n" \
" \n" \
diff --git a/src/core/job.c b/src/core/job.c
index f08b8cb..d5f4a21 100644
--- a/src/core/job.c
+++ b/src/core/job.c
@@ -825,6 +825,16 @@ finish:
if (other->job)
job_add_to_run_queue(other->job);
+ /* Trigger OnStop dependencies that */
+ if ((result == JOB_DONE) && ( t == JOB_STOP)) {
+ log_notice("Job %s/%s completed with result '%s/%d'. Triggering OnStop events",
+ u->id,
+ job_type_to_string(t),
+ job_result_to_string(result), result);
+
+ unit_trigger_on_stop(u);
+ }
+
manager_check_finished(u->manager);
return 0;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index be16ba9..d93d13f 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -108,6 +108,7 @@ Unit.Conflicts, config_parse_unit_deps, UNIT_CONFLI
Unit.Before, config_parse_unit_deps, UNIT_BEFORE, 0
Unit.After, config_parse_unit_deps, UNIT_AFTER, 0
Unit.OnFailure, config_parse_unit_deps, UNIT_ON_FAILURE, 0
+Unit.OnStop, config_parse_unit_deps, UNIT_ON_STOP, 0
Unit.PropagatesReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
Unit.PropagateReloadTo, config_parse_unit_deps, UNIT_PROPAGATES_RELOAD_TO, 0
Unit.ReloadPropagatedFrom, config_parse_unit_deps, UNIT_RELOAD_PROPAGATED_FROM, 0
diff --git a/src/core/unit.c b/src/core/unit.c
index 99e1c27..564e16c 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1316,6 +1316,25 @@ void unit_trigger_on_failure(Unit *u) {
}
}
+void unit_trigger_on_stop(Unit *u) {
+ Unit *other;
+ Iterator i;
+
+ assert(u);
+
+ if (set_size(u->dependencies[UNIT_ON_STOP]) <= 0)
+ return;
+
+ log_info("Triggering OnStop= dependencies of %s.", u->id);
+
+ SET_FOREACH(other, u->dependencies[UNIT_ON_STOP], i) {
+ int r;
+
+ if ((r = manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL)) < 0)
+ log_error("Failed to enqueue OnStop= job: %s", strerror(-r));
+ }
+}
+
void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success) {
bool unexpected;
@@ -1693,6 +1712,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
[UNIT_BEFORE] = UNIT_AFTER,
[UNIT_AFTER] = UNIT_BEFORE,
[UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
+ [UNIT_ON_STOP] = _UNIT_DEPENDENCY_INVALID,
[UNIT_REFERENCES] = UNIT_REFERENCED_BY,
[UNIT_REFERENCED_BY] = UNIT_REFERENCES,
[UNIT_TRIGGERS] = UNIT_TRIGGERED_BY,
@@ -2727,6 +2747,7 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
[UNIT_BEFORE] = "Before",
[UNIT_AFTER] = "After",
[UNIT_ON_FAILURE] = "OnFailure",
+ [UNIT_ON_STOP] = "OnStop",
[UNIT_TRIGGERS] = "Triggers",
[UNIT_TRIGGERED_BY] = "TriggeredBy",
[UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo",
diff --git a/src/core/unit.h b/src/core/unit.h
index bf961c2..1ca0931 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -95,6 +95,9 @@ enum UnitDependency {
/* On Failure */
UNIT_ON_FAILURE,
+ /* On Stop */
+ UNIT_ON_STOP,
+
/* Triggers (i.e. a socket triggers a service) */
UNIT_TRIGGERS,
UNIT_TRIGGERED_BY,
@@ -528,6 +531,8 @@ int unit_following_set(Unit *u, Set **s);
void unit_trigger_on_failure(Unit *u);
+void unit_trigger_on_stop(Unit *u);
+
bool unit_condition_test(Unit *u);
UnitFileState unit_get_unit_file_state(Unit *u);