[systemd-devel] [PATCH 3/6] [RFE] Add OnStop rule

Oleksii Shevchuk alxchk at gmail.com
Sat Nov 3 12:52:01 PDT 2012


Add deps to run when unit successfuly stopped
---
 man/systemd.unit.xml                  | 10 ++++++++++
 src/core/dbus-unit.c                  |  1 +
 src/core/dbus-unit.h                  |  1 +
 src/core/job.c                        | 10 ++++++++++
 src/core/load-fragment-gperf.gperf.m4 |  1 +
 src/core/unit.c                       | 21 +++++++++++++++++++++
 src/core/unit.h                       |  5 +++++
 7 files changed, 49 insertions(+)

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 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><varname>OnStop=</varname></term>
+
+                                <listitem><para>Lists one or more
+                                units that are activated when this
+                                unit enters the
+                                '<literal>stop</literal>'
+                                state.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><varname>PropagatesReloadTo=</varname></term>
                                 <term><varname>ReloadPropagatedFrom=</varname></term>
 
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 @@
         "  <property name=\"Before\" type=\"as\" access=\"read\"/>\n"   \
         "  <property name=\"After\" type=\"as\" access=\"read\"/>\n"    \
         "  <property name=\"OnFailure\" type=\"as\" access=\"read\"/>\n"    \
+        "  <property name=\"OnStop\" type=\"as\" access=\"read\"/>\n"    \
         "  <property name=\"Triggers\" type=\"as\" access=\"read\"/>\n"    \
         "  <property name=\"TriggeredBy\" type=\"as\" access=\"read\"/>\n"    \
         "  <property name=\"PropagatesReloadTo\" type=\"as\" access=\"read\"/>\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);
-- 
1.7.12.4



More information about the systemd-devel mailing list