diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 120ffbc8ef..689ca3ec88 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -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 { + + @@ -2406,6 +2409,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { Transient contains a boolean that indicates whether the unit was created as a transient unit (i.e. via CreateTransientUnit() on the manager object). + + ActivationDetails 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.: trigger_unit, with value foo.service). This is only filled + in if the unit was triggered by a Path or Timer 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 Environment Variables Set on Triggered Units section in + systemd.exec1. + Note that new key value pair may be added at any time in future versions. Existing entries will not be + removed. @@ -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 { + + @@ -10709,6 +10728,9 @@ node /org/freedesktop/systemd1/job/666 { State refers to the job's state and is one of waiting and running. 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. + + ActivationDetails has the same content as the property of the same name under + the org.freedesktop.systemd1.Unit interface. diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index de474e6d4e..7b1438266b 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -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 }; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index ee013e1bc5..7a16471758 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -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), diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c index 264a4f55b6..edfa0eb69a 100644 --- a/src/core/dbus-util.c +++ b/src/core/dbus-util.c @@ -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); +} diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h index 799136737b..e12631a0e2 100644 --- a/src/core/dbus-util.h +++ b/src/core/dbus-util.h @@ -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); diff --git a/src/core/job.c b/src/core/job.c index 6653dbde84..dd8d858bd2 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -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); +} diff --git a/src/core/job.h b/src/core/job.h index c033c8a4fa..0305e0ea44 100644 --- a/src/core/job.h +++ b/src/core/job.h @@ -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); diff --git a/src/core/service.c b/src/core/service.c index a715a1d1dc..fa37207dcc 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -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; diff --git a/src/core/unit.c b/src/core/unit.c index 6242f045b4..18d9ba85de 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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); diff --git a/src/core/unit.h b/src/core/unit.h index 4dabbb9a3c..fc8edaade5 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -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); diff --git a/src/test/test-bpf-firewall.c b/src/test/test-bpf-firewall.c index 3b99c5aaec..d655058d3d 100644 --- a/src/test/test-bpf-firewall.c +++ b/src/test/test-bpf-firewall.c @@ -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); diff --git a/src/test/test-bpf-foreign-programs.c b/src/test/test-bpf-foreign-programs.c index 061426f287..0445c39855 100644 --- a/src/test/test-bpf-foreign-programs.c +++ b/src/test/test-bpf-foreign-programs.c @@ -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"); diff --git a/src/test/test-bpf-lsm.c b/src/test/test-bpf-lsm.c index 9709053d0a..e1df62f1a6 100644 --- a/src/test/test-bpf-lsm.c +++ b/src/test/test-bpf-lsm.c @@ -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"); diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 82e4cf5e54..0283caeca6 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -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) \ diff --git a/src/test/test-path.c b/src/test/test-path.c index 7fb1f7363c..a440ca08b4 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -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); diff --git a/src/test/test-socket-bind.c b/src/test/test-socket-bind.c index dadd2c0dff..d7d9110343 100644 --- a/src/test/test-socket-bind.c +++ b/src/test/test-socket-bind.c @@ -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");