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;