]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add basic infrastructure to record unit activation information
authorLuca Boccassi <bluca@debian.org>
Tue, 2 Aug 2022 18:49:20 +0000 (19:49 +0100)
committerLuca Boccassi <bluca@debian.org>
Tue, 23 Aug 2022 19:38:08 +0000 (20:38 +0100)
Not wired in by any unit type yet, just the basic to allocate,
ref, deref and plug in to other unit types.
Includes recording the trigger unit name and passing it to the
triggered unit as TRIGGER_UNIT= env var.

16 files changed:
man/org.freedesktop.systemd1.xml
src/core/dbus-job.c
src/core/dbus-unit.c
src/core/dbus-util.c
src/core/dbus-util.h
src/core/job.c
src/core/job.h
src/core/service.c
src/core/unit.c
src/core/unit.h
src/test/test-bpf-firewall.c
src/test/test-bpf-foreign-programs.c
src/test/test-bpf-lsm.c
src/test/test-execute.c
src/test/test-path.c
src/test/test-socket-bind.c

index 120ffbc8ef08edd43ab0d37f2f4416057f2285ae..689ca3ec88fc14cd6e70acee7fcf22376f30f6d9 100644 (file)
@@ -1898,6 +1898,7 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       readonly s CollectMode = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
       readonly as Refs = ['...', ...];
+      readonly a(ss) ActivationDetails = [...];
   };
   interface org.freedesktop.DBus.Peer { ... };
   interface org.freedesktop.DBus.Introspectable { ... };
@@ -2229,6 +2230,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="Refs"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="ActivationDetails"/>
+
     <!--End of Autogenerated section-->
 
     <refsect2>
@@ -2406,6 +2409,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
       <para><varname>Transient</varname> contains a boolean that indicates whether the unit was created as a
       transient unit (i.e. via <function>CreateTransientUnit()</function> on the manager object).</para>
+
+      <para><varname>ActivationDetails</varname> contains a list of string pairs, key and value, that
+      describe the event that caused the unit to be activated, if any. The key describes the information
+      (e.g.: <varname>trigger_unit</varname>, with value <varname>foo.service</varname>). This is only filled
+      in if the unit was triggered by a <varname>Path</varname> or <varname>Timer</varname> unit, and it is
+      only provided in a best effort fashion: it is not guaranteed to be set, and it is not guaranteed to be
+      the only trigger. It is only guaranteed to be a valid trigger that caused the activation job to be
+      enqueued and complete successfully. The key value pairs correspond (in lowercase) to the environment
+      variables described in the <literal>Environment Variables Set on Triggered Units</literal> section in
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+      Note that new key value pair may be added at any time in future versions. Existing entries will not be
+      removed.</para>
     </refsect2>
 
     <refsect2>
@@ -10650,6 +10665,8 @@ node /org/freedesktop/systemd1/job/666 {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s JobType = '...';
       readonly s State = '...';
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
+      readonly a(ss) ActivationDetails = [...];
   };
   interface org.freedesktop.DBus.Peer { ... };
   interface org.freedesktop.DBus.Introspectable { ... };
@@ -10681,6 +10698,8 @@ node /org/freedesktop/systemd1/job/666 {
 
     <variablelist class="dbus-property" generated="True" extra-ref="State"/>
 
+    <variablelist class="dbus-property" generated="True" extra-ref="ActivationDetails"/>
+
     <!--End of Autogenerated section-->
 
     <refsect2>
@@ -10709,6 +10728,9 @@ node /org/freedesktop/systemd1/job/666 {
       <para><varname>State</varname> refers to the job's state and is one of <literal>waiting</literal> and
       <literal>running</literal>. The former indicates that a job is currently queued but has not begun to
       execute yet. The latter indicates that a job is currently being executed.</para>
+
+      <para><varname>ActivationDetails</varname> has the same content as the property of the same name under
+      the <varname>org.freedesktop.systemd1.Unit</varname> interface.</para>
     </refsect2>
   </refsect1>
 
index de474e6d4e0a8701e1366160ff135236bc8f0352..7b1438266beae7fc949d4cbe360ad98174be788e 100644 (file)
@@ -7,6 +7,7 @@
 #include "bus-util.h"
 #include "dbus-job.h"
 #include "dbus-unit.h"
+#include "dbus-util.h"
 #include "dbus.h"
 #include "job.h"
 #include "log.h"
@@ -136,6 +137,7 @@ const sd_bus_vtable bus_job_vtable[] = {
         SD_BUS_PROPERTY("Unit", "(so)", property_get_unit, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("JobType", "s", property_get_type, offsetof(Job, type), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("State", "s", property_get_state, offsetof(Job, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("ActivationDetails", "a(ss)", bus_property_get_activation_details, offsetof(Job, activation_details), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_VTABLE_END
 };
 
index ee013e1bc5af37d43d9e68473da4bebf00bd7dde..7a16471758ee0f1baf3d178f2e4cb7aca2e0effd 100644 (file)
@@ -951,6 +951,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
         SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
+        SD_BUS_PROPERTY("ActivationDetails", "a(ss)", bus_property_get_activation_details, offsetof(Unit, activation_details), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
 
         SD_BUS_METHOD_WITH_ARGS("Start",
                                 SD_BUS_ARGS("s", mode),
index 264a4f55b67db379634c59ec8002fb04a2af4cd7..edfa0eb69a4f6ba4e239d05f18f75fa059461cdc 100644 (file)
@@ -228,3 +228,35 @@ int bus_read_mount_options(
 
         return 0;
 }
+
+int bus_property_get_activation_details(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        ActivationDetails **details = ASSERT_PTR(userdata);
+        _cleanup_strv_free_ char **pairs = NULL;
+        int r;
+
+        assert(reply);
+
+        r = activation_details_append_pair(*details, &pairs);
+        if (r < 0)
+                return r;
+
+        r = sd_bus_message_open_container(reply, 'a', "(ss)");
+        if (r < 0)
+                return r;
+
+        STRV_FOREACH_PAIR(key, value, pairs) {
+                r = sd_bus_message_append(reply, "(ss)", *key, *value);
+                if (r < 0)
+                        return r;
+        }
+
+        return sd_bus_message_close_container(reply);
+}
index 799136737ba225b2a169b9f87ae8bf8413fcac79..e12631a0e21c0dfe39b135eead2252034923dada 100644 (file)
@@ -251,3 +251,5 @@ static inline int bus_set_transient_usec_fix_0(Unit *u, const char *name, usec_t
 int bus_verify_manage_units_async_full(Unit *u, const char *verb, int capability, const char *polkit_message, bool interactive, sd_bus_message *call, sd_bus_error *error);
 
 int bus_read_mount_options(sd_bus_message *message, sd_bus_error *error, MountOptions **ret_options, char **ret_format_str, const char *separator);
+
+int bus_property_get_activation_details(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
index 6653dbde84b79acbf12036b0d78ff926eb6e371f..dd8d858bd2d945e9eb99ab1b98a5d55cfac1481f 100644 (file)
@@ -104,6 +104,8 @@ Job* job_free(Job *j) {
         sd_bus_track_unref(j->bus_track);
         strv_free(j->deserialized_clients);
 
+        activation_details_unref(j->activation_details);
+
         return mfree(j);
 }
 
@@ -180,9 +182,13 @@ static void job_merge_into_installed(Job *j, Job *other) {
         assert(j->installed);
         assert(j->unit == other->unit);
 
-        if (j->type != JOB_NOP)
+        if (j->type != JOB_NOP) {
                 assert_se(job_type_merge_and_collapse(&j->type, other->type, j->unit) == 0);
-        else
+
+                /* Keep the oldest ActivationDetails, if any */
+                if (!j->activation_details)
+                        j->activation_details = TAKE_PTR(other->activation_details);
+        } else
                 assert(other->type == JOB_NOP);
 
         j->irreversible = j->irreversible || other->irreversible;
@@ -776,6 +782,7 @@ static void job_emit_done_message(Unit *u, uint32_t job_id, JobType t, JobResult
 }
 
 static int job_perform_on_unit(Job **j) {
+        ActivationDetails *a;
         uint32_t id;
         Manager *m;
         JobType t;
@@ -795,10 +802,11 @@ static int job_perform_on_unit(Job **j) {
         u = (*j)->unit;
         t = (*j)->type;
         id = (*j)->id;
+        a = (*j)->activation_details;
 
         switch (t) {
                 case JOB_START:
-                        r = unit_start(u);
+                        r = unit_start(u, a);
                         break;
 
                 case JOB_RESTART:
@@ -1160,6 +1168,8 @@ int job_serialize(Job *j, FILE *f) {
 
         bus_track_serialize(j->bus_track, f, "subscribed");
 
+        activation_details_serialize(j->activation_details, f);
+
         /* End marker */
         fputc('\n', f);
         return 0;
@@ -1257,6 +1267,11 @@ int job_deserialize(Job *j, FILE *f) {
                 else if (streq(l, "subscribed")) {
                         if (strv_extend(&j->deserialized_clients, v) < 0)
                                 return log_oom();
+
+                } else if (startswith(l, "activation-details")) {
+                        if (activation_details_deserialize(l, v, &j->activation_details) < 0)
+                                log_debug("Failed to parse job ActivationDetails element: %s", v);
+
                 } else
                         log_debug("Unknown job serialization key: %s", l);
         }
@@ -1636,3 +1651,11 @@ int job_compare(Job *a, Job *b, UnitDependencyAtom assume_dep) {
         else
                 return -1;
 }
+
+void job_set_activation_details(Job *j, ActivationDetails *info) {
+        /* Existing (older) ActivationDetails win, newer ones are discarded. */
+        if (!j || j->activation_details || !info)
+                return; /* Nothing to do. */
+
+        j->activation_details = activation_details_ref(info);
+}
index c033c8a4faaa0e2d21615fcdac9e287c0364f672..0305e0ea4451244f4b8d64f626037cacf73d90b0 100644 (file)
@@ -10,6 +10,7 @@
 #include "unit-name.h"
 #include "unit.h"
 
+typedef struct ActivationDetails ActivationDetails;
 typedef struct Job Job;
 typedef struct JobDependency JobDependency;
 typedef enum JobType JobType;
@@ -151,6 +152,9 @@ struct Job {
 
         unsigned run_queue_idx;
 
+        /* If the job had a specific trigger that needs to be advertised (eg: a path unit), store it. */
+        ActivationDetails *activation_details;
+
         bool installed:1;
         bool in_run_queue:1;
         bool matters_to_anchor:1;
@@ -243,3 +247,5 @@ JobResult job_result_from_string(const char *s) _pure_;
 const char* job_type_to_access_method(JobType t);
 
 int job_compare(Job *a, Job *b, UnitDependencyAtom assume_dep);
+
+void job_set_activation_details(Job *j, ActivationDetails *info);
index a715a1d1dc82424be0041750aaaccfb5ee6585fd..fa37207dcca8df17e2f4d4de2b4143a9e9070701 100644 (file)
@@ -1641,6 +1641,16 @@ static int service_spawn_internal(
                 }
         }
 
+        if (UNIT(s)->activation_details) {
+                r = activation_details_append_env(UNIT(s)->activation_details, &our_env);
+                if (r < 0)
+                        return r;
+                /* The number of env vars added here can vary, rather than keeping the allocation block in
+                 * sync manually, these functions simply use the strv methods to append to it, so we need
+                 * to update n_env when we are done in case of future usage. */
+                n_env += r;
+        }
+
         r = unit_set_exec_params(UNIT(s), &exec_params);
         if (r < 0)
                 return r;
index 6242f045b430739bc57f43f30106865dea5ec45f..18d9ba85de3e60486e9c23c3cfdbf608d87288e2 100644 (file)
@@ -41,6 +41,7 @@
 #include "path-util.h"
 #include "process-util.h"
 #include "rm-rf.h"
+#include "serialize.h"
 #include "set.h"
 #include "signal-util.h"
 #include "sparse-endian.h"
@@ -807,6 +808,8 @@ Unit* unit_free(Unit *u) {
         set_free_free(u->aliases);
         free(u->id);
 
+        activation_details_unref(u->activation_details);
+
         return mfree(u);
 }
 
@@ -1188,6 +1191,9 @@ int unit_merge(Unit *u, Unit *other) {
         other->load_state = UNIT_MERGED;
         other->merged_into = u;
 
+        if (!u->activation_details)
+                u->activation_details = activation_details_ref(other->activation_details);
+
         /* If there is still some data attached to the other node, we
          * don't need it anymore, and can free it. */
         if (other->load_state != UNIT_STUB)
@@ -1861,7 +1867,7 @@ static bool unit_verify_deps(Unit *u) {
  *         -ESTALE:     This unit has been started before and can't be started a second time
  *         -ENOENT:     This is a triggering unit and unit to trigger is not loaded
  */
-int unit_start(Unit *u) {
+int unit_start(Unit *u, ActivationDetails *details) {
         UnitActiveState state;
         Unit *following;
         int r;
@@ -1918,7 +1924,7 @@ int unit_start(Unit *u) {
         following = unit_following(u);
         if (following) {
                 log_unit_debug(u, "Redirecting start request from %s to %s.", u->id, following->id);
-                return unit_start(following);
+                return unit_start(following, details);
         }
 
         /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
@@ -1939,6 +1945,9 @@ int unit_start(Unit *u) {
         unit_add_to_dbus_queue(u);
         unit_cgroup_freezer_action(u, FREEZER_THAW);
 
+        if (!u->activation_details) /* Older details object wins */
+                u->activation_details = activation_details_ref(details);
+
         return UNIT_VTABLE(u)->start(u);
 }
 
@@ -5919,3 +5928,152 @@ int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***re
         assert(n <= INT_MAX);
         return (int) n;
 }
+
+const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX] = {
+};
+
+ActivationDetails *activation_details_new(Unit *trigger_unit) {
+        _cleanup_free_ ActivationDetails *details = NULL;
+
+        assert(trigger_unit);
+        assert(trigger_unit->type != _UNIT_TYPE_INVALID);
+        assert(trigger_unit->id);
+
+        details = malloc0(activation_details_vtable[trigger_unit->type]->object_size);
+        if (!details)
+                return NULL;
+
+        *details = (ActivationDetails) {
+                .n_ref = 1,
+                .trigger_unit_type = trigger_unit->type,
+        };
+
+        details->trigger_unit_name = strdup(trigger_unit->id);
+        if (!details->trigger_unit_name)
+                return NULL;
+
+        if (ACTIVATION_DETAILS_VTABLE(details)->init)
+                ACTIVATION_DETAILS_VTABLE(details)->init(details, trigger_unit);
+
+        return TAKE_PTR(details);
+}
+
+static ActivationDetails *activation_details_free(ActivationDetails *details) {
+        if (!details)
+                return NULL;
+
+        if (ACTIVATION_DETAILS_VTABLE(details)->done)
+                ACTIVATION_DETAILS_VTABLE(details)->done(details);
+
+        free(details->trigger_unit_name);
+
+        return mfree(details);
+}
+
+void activation_details_serialize(ActivationDetails *details, FILE *f) {
+        if (!details || details->trigger_unit_type == _UNIT_TYPE_INVALID)
+                return;
+
+        (void) serialize_item(f, "activation-details-unit-type", unit_type_to_string(details->trigger_unit_type));
+        if (details->trigger_unit_name)
+                (void) serialize_item(f, "activation-details-unit-name", details->trigger_unit_name);
+        if (ACTIVATION_DETAILS_VTABLE(details)->serialize)
+                ACTIVATION_DETAILS_VTABLE(details)->serialize(details, f);
+}
+
+int activation_details_deserialize(const char *key, const char *value, ActivationDetails **details) {
+        assert(key);
+        assert(value);
+        assert(details);
+
+        if (!*details) {
+                UnitType t;
+
+                if (!streq(key, "activation-details-unit-type"))
+                        return -EINVAL;
+
+                t = unit_type_from_string(value);
+                if (t == _UNIT_TYPE_INVALID)
+                        return -EINVAL;
+
+                *details = malloc0(activation_details_vtable[t]->object_size);
+                if (!*details)
+                        return -ENOMEM;
+
+                **details = (ActivationDetails) {
+                        .n_ref = 1,
+                        .trigger_unit_type = t,
+                };
+
+                return 0;
+        }
+
+        if (streq(key, "activation-details-unit-name")) {
+                (*details)->trigger_unit_name = strdup(value);
+                if (!(*details)->trigger_unit_name)
+                        return -ENOMEM;
+
+                return 0;
+        }
+
+        if (ACTIVATION_DETAILS_VTABLE(*details)->deserialize)
+                return ACTIVATION_DETAILS_VTABLE(*details)->deserialize(key, value, details);
+
+        return -EINVAL;
+}
+
+int activation_details_append_env(ActivationDetails *details, char ***strv) {
+        int r = 0;
+
+        assert(strv);
+
+        if (!details)
+                return 0;
+
+        if (!isempty(details->trigger_unit_name)) {
+                char *s = strjoin("TRIGGER_UNIT=", details->trigger_unit_name);
+                if (!s)
+                        return -ENOMEM;
+
+                r = strv_consume(strv, TAKE_PTR(s));
+                if (r < 0)
+                        return r;
+        }
+
+        if (ACTIVATION_DETAILS_VTABLE(details)->append_env) {
+                r = ACTIVATION_DETAILS_VTABLE(details)->append_env(details, strv);
+                if (r < 0)
+                        return r;
+        }
+
+        return r + !isempty(details->trigger_unit_name); /* Return the number of variables added to the env block */
+}
+
+int activation_details_append_pair(ActivationDetails *details, char ***strv) {
+        int r = 0;
+
+        assert(strv);
+
+        if (!details)
+                return 0;
+
+        if (!isempty(details->trigger_unit_name)) {
+                r = strv_extend(strv, "trigger_unit");
+                if (r < 0)
+                        return r;
+
+                r = strv_extend(strv, details->trigger_unit_name);
+                if (r < 0)
+                        return r;
+        }
+
+        if (ACTIVATION_DETAILS_VTABLE(details)->append_env) {
+                r = ACTIVATION_DETAILS_VTABLE(details)->append_pair(details, strv);
+                if (r < 0)
+                        return r;
+        }
+
+        return r + !isempty(details->trigger_unit_name); /* Return the number of pairs added to the strv */
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(ActivationDetails, activation_details, activation_details_free);
index 4dabbb9a3c93fcd94243759b88bc1d60d8acaa8a..fc8edaade53ecea791b1e0249c9c7ac7056af878 100644 (file)
@@ -110,6 +110,75 @@ typedef union UnitDependencyInfo {
         } _packed_;
 } UnitDependencyInfo;
 
+/* Store information about why a unit was activated.
+ * We start with trigger units (.path/.timer), eventually it will be expanded to include more metadata. */
+typedef struct ActivationDetails {
+        unsigned n_ref;
+        UnitType trigger_unit_type;
+        char *trigger_unit_name;
+} ActivationDetails;
+
+/* For casting an activation event into the various unit-specific types */
+#define DEFINE_ACTIVATION_DETAILS_CAST(UPPERCASE, MixedCase, UNIT_TYPE)         \
+        static inline MixedCase* UPPERCASE(ActivationDetails *a) {              \
+                if (_unlikely_(!a || a->trigger_unit_type != UNIT_##UNIT_TYPE)) \
+                        return NULL;                                            \
+                                                                                \
+                return (MixedCase*) a;                                          \
+        }
+
+/* For casting the various unit types into a unit */
+#define ACTIVATION_DETAILS(u)                                         \
+        ({                                                            \
+                typeof(u) _u_ = (u);                                  \
+                ActivationDetails *_w_ = _u_ ? &(_u_)->meta : NULL;   \
+                _w_;                                                  \
+        })
+
+ActivationDetails *activation_details_new(Unit *trigger_unit);
+ActivationDetails *activation_details_ref(ActivationDetails *p);
+ActivationDetails *activation_details_unref(ActivationDetails *p);
+void activation_details_serialize(ActivationDetails *p, FILE *f);
+int activation_details_deserialize(const char *key, const char *value, ActivationDetails **info);
+int activation_details_append_env(ActivationDetails *info, char ***strv);
+int activation_details_append_pair(ActivationDetails *info, char ***strv);
+DEFINE_TRIVIAL_CLEANUP_FUNC(ActivationDetails*, activation_details_unref);
+
+typedef struct ActivationDetailsVTable {
+        /* How much memory does an object of this activation type need */
+        size_t object_size;
+
+        /* This should reset all type-specific variables. This should not allocate memory, and is called
+         * with zero-initialized data. It should hence only initialize variables that need to be set != 0. */
+        void (*init)(ActivationDetails *info, Unit *trigger_unit);
+
+        /* This should free all type-specific variables. It should be idempotent. */
+        void (*done)(ActivationDetails *info);
+
+        /* This should serialize all type-specific variables. */
+        void (*serialize)(ActivationDetails *info, FILE *f);
+
+        /* This should deserialize all type-specific variables, one at a time. */
+        int (*deserialize)(const char *key, const char *value, ActivationDetails **info);
+
+        /* This should format the type-specific variables for the env block of the spawned service,
+         * and return the number of added items. */
+        int (*append_env)(ActivationDetails *info, char ***strv);
+
+        /* This should append type-specific variables as key/value pairs for the D-Bus property of the job,
+         * and return the number of added pairs. */
+        int (*append_pair)(ActivationDetails *info, char ***strv);
+} ActivationDetailsVTable;
+
+extern const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX];
+
+static inline const ActivationDetailsVTable* ACTIVATION_DETAILS_VTABLE(const ActivationDetails *a) {
+        assert(a);
+        assert(a->trigger_unit_type < _UNIT_TYPE_MAX);
+
+        return activation_details_vtable[a->trigger_unit_type];
+}
+
 /* Newer LLVM versions don't like implicit casts from large pointer types to smaller enums, hence let's add
  * explicit type-safe helpers for that. */
 static inline UnitDependency UNIT_DEPENDENCY_FROM_PTR(const void *p) {
@@ -363,6 +432,9 @@ typedef struct Unit {
         JobMode on_success_job_mode;
         JobMode on_failure_job_mode;
 
+        /* If the job had a specific trigger that needs to be advertised (eg: a path unit), store it. */
+        ActivationDetails *activation_details;
+
         /* Tweaking the GC logic */
         CollectMode collect_mode;
 
@@ -813,7 +885,7 @@ bool unit_can_start(Unit *u) _pure_;
 bool unit_can_stop(Unit *u) _pure_;
 bool unit_can_isolate(Unit *u) _pure_;
 
-int unit_start(Unit *u);
+int unit_start(Unit *u, ActivationDetails *details);
 int unit_stop(Unit *u);
 int unit_reload(Unit *u);
 
index 3b99c5aaecb9d0e57a9ca5011cb281ae2ed2f1d8..d655058d3da7afd4b2523a405c6d82814c74edbd 100644 (file)
@@ -176,7 +176,7 @@ int main(int argc, char *argv[]) {
 
         assert_se(r >= 0);
 
-        assert_se(unit_start(u) >= 0);
+        assert_se(unit_start(u, NULL) >= 0);
 
         while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED))
                 assert_se(sd_event_run(m->event, UINT64_MAX) >= 0);
@@ -201,7 +201,7 @@ int main(int argc, char *argv[]) {
                 SERVICE(u)->type = SERVICE_ONESHOT;
                 u->load_state = UNIT_LOADED;
 
-                assert_se(unit_start(u) >= 0);
+                assert_se(unit_start(u, NULL) >= 0);
 
                 while (!IN_SET(SERVICE(u)->state, SERVICE_DEAD, SERVICE_FAILED))
                         assert_se(sd_event_run(m->event, UINT64_MAX) >= 0);
index 061426f28720f24ac310c2c9267696f8a8053651..0445c39855ff3a317b64c6ed29c5fcdd541cadc3 100644 (file)
@@ -246,7 +246,7 @@ static int test_bpf_cgroup_programs(Manager *m, const char *unit_name, const Tes
         SERVICE(u)->type = SERVICE_ONESHOT;
         u->load_state = UNIT_LOADED;
 
-        r = unit_start(u);
+        r = unit_start(u, NULL);
         if (r < 0)
                 return log_error_errno(r, "Unit start failed %m");
 
index 9709053d0af4d73f964ee586f1c8ef04f5b50c76..e1df62f1a68797802a80c7045592300061c33014 100644 (file)
@@ -39,7 +39,7 @@ static int test_restrict_filesystems(Manager *m, const char *unit_name, const ch
         SERVICE(u)->type = SERVICE_ONESHOT;
         u->load_state = UNIT_LOADED;
 
-        r = unit_start(u);
+        r = unit_start(u, NULL);
         if (r < 0)
                 return log_error_errno(r, "Unit start failed %m");
 
index 82e4cf5e54d413c9dfacf89249bbc852e2cb4dcd..0283caeca618227e0513a3187eeeaf6ec8679581 100644 (file)
@@ -210,7 +210,7 @@ static void _test(const char *file, unsigned line, const char *func,
         assert_se(unit_name);
 
         assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         check_main_result(file, line, func, m, unit, status_expected, code_expected);
 }
 #define test(m, unit_name, status_expected, code_expected) \
@@ -223,7 +223,7 @@ static void _test_service(const char *file, unsigned line, const char *func,
         assert_se(unit_name);
 
         assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         check_service_result(file, line, func, m, unit, result_expected);
 }
 #define test_service(m, unit_name, result_expected) \
index 7fb1f7363c77e942cdd7b1bd5b8a4d50b99ec89b..a440ca08b479a64b433a3518046a09b36d4d4b7f 100644 (file)
@@ -136,7 +136,7 @@ static void test_path_exists(Manager *m) {
         path = PATH(unit);
         service = service_for_path(m, path, NULL);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -170,7 +170,7 @@ static void test_path_existsglob(Manager *m) {
         path = PATH(unit);
         service = service_for_path(m, path, NULL);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -205,7 +205,7 @@ static void test_path_changed(Manager *m) {
         path = PATH(unit);
         service = service_for_path(m, path, NULL);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -247,7 +247,7 @@ static void test_path_modified(Manager *m) {
         path = PATH(unit);
         service = service_for_path(m, path, NULL);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -288,7 +288,7 @@ static void test_path_unit(Manager *m) {
         path = PATH(unit);
         service = service_for_path(m, path, "path-mycustomunit.service");
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -319,7 +319,7 @@ static void test_path_directorynotempty(Manager *m) {
 
         assert_se(access(test_path, F_OK) < 0);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
         if (check_states(m, path, service, PATH_WAITING, SERVICE_DEAD) < 0)
                 return;
 
@@ -356,7 +356,7 @@ static void test_path_makedirectory_directorymode(Manager *m) {
 
         assert_se(access(test_path, F_OK) < 0);
 
-        assert_se(unit_start(unit) >= 0);
+        assert_se(unit_start(unit, NULL) >= 0);
 
         /* Check if the directory has been created */
         assert_se(access(test_path, F_OK) >= 0);
index dadd2c0dff61c0aa29c1e5565ebc387359a3f6e2..d7d911034321d6b4b2eabed7c281def93db10ea4 100644 (file)
@@ -78,7 +78,7 @@ static int test_socket_bind(
         SERVICE(u)->type = SERVICE_ONESHOT;
         u->load_state = UNIT_LOADED;
 
-        r = unit_start(u);
+        r = unit_start(u, NULL);
         if (r < 0)
                 return log_error_errno(r, "Unit start failed %m");