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);