diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index c5e84d7..623b225 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -644,6 +644,18 @@ + OnStopRestoreConflicts= + + Takes a boolean + argument. If all + jobs stopped as conflicted by this unit + will be started on successfull stop of this + unit. + Defaults to + . + + + IgnoreOnIsolate= Takes a boolean diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 347263a..05f4039 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -841,6 +841,7 @@ const BusProperty bus_unit_properties[] = { { "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 }, + { "OnStopRestoreConflicts",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS]), 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 }, @@ -873,6 +874,7 @@ const BusProperty bus_unit_properties[] = { { "AllowIsolate", bus_property_append_bool, "b", offsetof(Unit, allow_isolate) }, { "DefaultDependencies", bus_property_append_bool, "b", offsetof(Unit, default_dependencies) }, { "OnFailureIsolate", bus_property_append_bool, "b", offsetof(Unit, on_failure_isolate) }, + { "OnStopRestoreConflicts",bus_property_append_bool, "b", offsetof(Unit, on_stop_restore_conflicts) }, { "IgnoreOnIsolate", bus_property_append_bool, "b", offsetof(Unit, ignore_on_isolate) }, { "IgnoreOnSnapshot", bus_property_append_bool, "b", offsetof(Unit, ignore_on_snapshot) }, { "DefaultControlGroup", bus_unit_append_default_cgroup, "s", 0 }, diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h index b614bb1..6e8bcf8 100644 --- a/src/core/dbus-unit.h +++ b/src/core/dbus-unit.h @@ -112,6 +112,7 @@ " \n" \ " \n" \ " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index d93d13f..eb5b583 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -121,6 +121,7 @@ Unit.RefuseManualStop, config_parse_bool, 0, Unit.AllowIsolate, config_parse_bool, 0, offsetof(Unit, allow_isolate) Unit.DefaultDependencies, config_parse_bool, 0, offsetof(Unit, default_dependencies) Unit.OnFailureIsolate, config_parse_bool, 0, offsetof(Unit, on_failure_isolate) +Unit.OnStopRestoreConflicts, config_parse_bool, 0, offsetof(Unit, on_stop_restore_conflicts) Unit.IgnoreOnIsolate, config_parse_bool, 0, offsetof(Unit, ignore_on_isolate) Unit.IgnoreOnSnapshot, config_parse_bool, 0, offsetof(Unit, ignore_on_snapshot) Unit.JobTimeoutSec, config_parse_usec, 0, offsetof(Unit, job_timeout) diff --git a/src/core/transaction.c b/src/core/transaction.c index 4bce942..702a94f 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -956,6 +956,9 @@ int transaction_add_job_and_dependencies( if (e) dbus_error_free(e); + } else if (ret->unit->on_stop_restore_conflicts) { + log_notice("Add %s to %s OnStopReferencedBy queue\n", ret->unit->id, dep->id); + unit_add_dependency(dep, UNIT_ON_STOP_RESTORE_CONFLICTS_BY, ret->unit, false); } } @@ -966,6 +969,9 @@ int transaction_add_job_and_dependencies( if (e) dbus_error_free(e); + } else if (ret->unit->on_stop_restore_conflicts) { + log_notice("Add %s to %s OnStopReferencedBy queue (CB)\n", ret->unit->id, dep->id); + unit_add_dependency(dep, UNIT_ON_STOP_RESTORE_CONFLICTS_BY, ret->unit, false); } } diff --git a/src/core/unit.c b/src/core/unit.c index 564e16c..da36cb2 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -729,6 +729,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { "%s\tRefuseManualStop: %s\n" "%s\tDefaultDependencies: %s\n" "%s\tOnFailureIsolate: %s\n" + "%s\tOnStopRestoreConflicts: %s\n" "%s\tIgnoreOnIsolate: %s\n" "%s\tIgnoreOnSnapshot: %s\n", prefix, yes_no(u->stop_when_unneeded), @@ -736,6 +737,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { prefix, yes_no(u->refuse_manual_stop), prefix, yes_no(u->default_dependencies), prefix, yes_no(u->on_failure_isolate), + prefix, yes_no(u->on_stop_restore_conflicts), prefix, yes_no(u->ignore_on_isolate), prefix, yes_no(u->ignore_on_snapshot)); @@ -1322,16 +1324,41 @@ void unit_trigger_on_stop(Unit *u) { assert(u); - if (set_size(u->dependencies[UNIT_ON_STOP]) <= 0) - return; + if (set_size(u->dependencies[UNIT_ON_STOP]) > 0) + { + log_info("Triggering OnStop= dependencies of %s.", u->id); - log_info("Triggering OnStop= dependencies of %s.", u->id); + SET_FOREACH(other, u->dependencies[UNIT_ON_STOP], i) { + int r; - 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)); + } + } + + if (set_size(u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS_BY]) > 0) + { + log_notice("Setting up OnStopRestoreConflicts virtual deps for Conflicted units\n"); + SET_FOREACH(other, u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS_BY], i) { + log_notice("Add %s to %s OnStop queue\n", u->id, other->id); + unit_add_dependency(other, UNIT_ON_STOP_RESTORE_CONFLICTS, u, true); + } + + set_clear(u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS_BY]); + } + + if (set_size(u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS]) > 0) + { + log_info("Triggering OnStopRestoreConflicts= virtual dependencies of %s.", u->id); + + SET_FOREACH(other, u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS], 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)); + } - 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)); + set_clear(u->dependencies[UNIT_ON_STOP_RESTORE_CONFLICTS]); } } @@ -1713,6 +1740,8 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_AFTER] = UNIT_BEFORE, [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID, [UNIT_ON_STOP] = _UNIT_DEPENDENCY_INVALID, + [UNIT_ON_STOP_RESTORE_CONFLICTS] = _UNIT_DEPENDENCY_INVALID, + [UNIT_ON_STOP_RESTORE_CONFLICTS_BY] = _UNIT_DEPENDENCY_INVALID, [UNIT_REFERENCES] = UNIT_REFERENCED_BY, [UNIT_REFERENCED_BY] = UNIT_REFERENCES, [UNIT_TRIGGERS] = UNIT_TRIGGERED_BY, @@ -2748,6 +2777,7 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_AFTER] = "After", [UNIT_ON_FAILURE] = "OnFailure", [UNIT_ON_STOP] = "OnStop", + [UNIT_ON_STOP_RESTORE_CONFLICTS] = "OnStopRestoreConflicts", [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 1ca0931..8be83f6 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -97,6 +97,8 @@ enum UnitDependency { /* On Stop */ UNIT_ON_STOP, + UNIT_ON_STOP_RESTORE_CONFLICTS, + UNIT_ON_STOP_RESTORE_CONFLICTS_BY, /* Triggers (i.e. a socket triggers a service) */ UNIT_TRIGGERS, @@ -218,6 +220,9 @@ struct Unit { /* Isolate OnFailure unit */ bool on_failure_isolate; + /* Enqueue conflits to OnStop */ + bool on_stop_restore_conflicts; + /* Ignore this unit when isolating */ bool ignore_on_isolate;