]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
service: set TRIGGER_UNIT= and TRIGGER_TIMER_REALTIME_USEC/MONOTONIC_USEC on activati... 24071/head
authorLuca Boccassi <bluca@debian.org>
Tue, 2 Aug 2022 19:15:12 +0000 (20:15 +0100)
committerLuca Boccassi <bluca@debian.org>
Tue, 23 Aug 2022 20:19:54 +0000 (21:19 +0100)
Same as path unit, best effort.

man/systemd.exec.xml
man/systemd.timer.xml
src/core/timer.c
src/core/timer.h
src/core/unit.c
test/units/testsuite-07.sh

index 2acb737c38f5f6e71ef920dbda048589f5f191ee..2e843be2e5446df15ae0a6245b935bf5984bd2b6 100644 (file)
@@ -3698,8 +3698,10 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
         <varlistentry>
           <term><varname>$TRIGGER_UNIT</varname></term>
           <term><varname>$TRIGGER_PATH</varname></term>
+          <term><varname>$TRIGGER_TIMER_REALTIME_USEC</varname></term>
+          <term><varname>$TRIGGER_TIMER_MONOTONIC_USEC</varname></term>
 
-          <listitem><para>If the unit was activated dynamically (e.g.: a corresponding path unit), the
+          <listitem><para>If the unit was activated dynamically (e.g.: a corresponding path unit or timer unit), the
           unit that triggered it and other type-dependent information will be passed via these variables. Note that
           this information is provided in a best-effort way. For example, multiple triggers happening one after
           another will be coalesced and only one will be reported, with no guarantee as to which one it will be.
index 49bcb18be52b7add99cb8b78c25a1d66d96d5ef8..953faa9b3342af42f1658dc1dcafcc3a1b97c1e5 100644 (file)
 
   <refsect1>
       <title>See Also</title>
+      <para>Environment variables with details on the trigger will be set for triggered units. See the
+      <literal>Environment Variables Set on Triggered Units</literal> section in
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+      for more details.</para>
       <para>
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
index 9de325ba66240af365e0d9ca1b00d1187ed79373..b89d593b7598b1aa60ad140882da5d7041cb3e32 100644 (file)
@@ -576,8 +576,10 @@ fail:
 }
 
 static void timer_enter_running(Timer *t) {
+        _cleanup_(activation_details_unrefp) ActivationDetails *details = NULL;
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         Unit *trigger;
+        Job *job;
         int r;
 
         assert(t);
@@ -593,11 +595,20 @@ static void timer_enter_running(Timer *t) {
                 return;
         }
 
-        r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
+        details = activation_details_new(UNIT(t));
+        if (!details) {
+                r = -ENOMEM;
+                goto fail;
+        }
+
+        r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, &job);
         if (r < 0)
                 goto fail;
 
         dual_timestamp_get(&t->last_trigger);
+        ACTIVATION_DETAILS_TIMER(details)->last_trigger = t->last_trigger;
+
+        job_set_activation_details(job, details);
 
         if (t->stamp_path)
                 touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
@@ -892,6 +903,91 @@ static int timer_can_start(Unit *u) {
         return 1;
 }
 
+static void activation_details_timer_serialize(ActivationDetails *details, FILE *f) {
+        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+
+        assert(details);
+        assert(f);
+        assert(t);
+
+        (void) serialize_dual_timestamp(f, "activation-details-timer-last-trigger", &t->last_trigger);
+}
+
+static int activation_details_timer_deserialize(const char *key, const char *value, ActivationDetails **details) {
+        int r;
+
+        assert(key);
+        assert(value);
+
+        if (!details || !*details)
+                return -EINVAL;
+
+        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(*details);
+        if (!t)
+                return -EINVAL;
+
+        if (!streq(key, "activation-details-timer-last-trigger"))
+                return -EINVAL;
+
+        r = deserialize_dual_timestamp(value, &t->last_trigger);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+static int activation_details_timer_append_env(ActivationDetails *details, char ***strv) {
+        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+        int r;
+
+        assert(details);
+        assert(strv);
+        assert(t);
+
+        if (!dual_timestamp_is_set(&t->last_trigger))
+                return 0;
+
+        r = strv_extendf(strv, "TRIGGER_TIMER_REALTIME_USEC=%" USEC_FMT, t->last_trigger.realtime);
+        if (r < 0)
+                return r;
+
+        r = strv_extendf(strv, "TRIGGER_TIMER_MONOTONIC_USEC=%" USEC_FMT, t->last_trigger.monotonic);
+        if (r < 0)
+                return r;
+
+        return 2; /* Return the number of variables added to the env block */
+}
+
+static int activation_details_timer_append_pair(ActivationDetails *details, char ***strv) {
+        ActivationDetailsTimer *t = ACTIVATION_DETAILS_TIMER(details);
+        int r;
+
+        assert(details);
+        assert(strv);
+        assert(t);
+
+        if (!dual_timestamp_is_set(&t->last_trigger))
+                return 0;
+
+        r = strv_extend(strv, "trigger_timer_realtime_usec");
+        if (r < 0)
+                return r;
+
+        r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.realtime);
+        if (r < 0)
+                return r;
+
+        r = strv_extend(strv, "trigger_timer_monotonic_usec");
+        if (r < 0)
+                return r;
+
+        r = strv_extendf(strv, "%" USEC_FMT, t->last_trigger.monotonic);
+        if (r < 0)
+                return r;
+
+        return 2; /* Return the number of pairs added to the env block */
+}
+
 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
         [TIMER_ACTIVE]        = "OnActiveSec",
         [TIMER_BOOT]          = "OnBootSec",
@@ -954,3 +1050,12 @@ const UnitVTable timer_vtable = {
 
         .can_start = timer_can_start,
 };
+
+const ActivationDetailsVTable activation_details_timer_vtable = {
+        .object_size = sizeof(ActivationDetailsTimer),
+
+        .serialize = activation_details_timer_serialize,
+        .deserialize = activation_details_timer_deserialize,
+        .append_env = activation_details_timer_append_env,
+        .append_pair = activation_details_timer_append_pair,
+};
index 551e2833417d4be1b2383aea8a89bd32c5988b19..914e42580e350840d0ed712dbaf72c2ccd524f4a 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 typedef struct Timer Timer;
+typedef struct ActivationDetailsTimer ActivationDetailsTimer;
 
 #include "calendarspec.h"
 #include "unit.h"
@@ -64,11 +65,17 @@ struct Timer {
         char *stamp_path;
 };
 
+struct ActivationDetailsTimer {
+        ActivationDetails meta;
+        dual_timestamp last_trigger;
+};
+
 #define TIMER_MONOTONIC_CLOCK(t) ((t)->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC)
 
 void timer_free_values(Timer *t);
 
 extern const UnitVTable timer_vtable;
+extern const ActivationDetailsVTable activation_details_timer_vtable;
 
 const char *timer_base_to_string(TimerBase i) _const_;
 TimerBase timer_base_from_string(const char *s) _pure_;
@@ -77,3 +84,4 @@ const char* timer_result_to_string(TimerResult i) _const_;
 TimerResult timer_result_from_string(const char *s) _pure_;
 
 DEFINE_CAST(TIMER, Timer);
+DEFINE_ACTIVATION_DETAILS_CAST(ACTIVATION_DETAILS_TIMER, ActivationDetailsTimer, TIMER);
index 4255e0cf1f43659b50534daeb11e9153f5c42474..5f1c6109b0bb89d427c837b47befb241cefd6209 100644 (file)
@@ -5931,6 +5931,7 @@ int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***re
 
 const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX] = {
         [UNIT_PATH] = &activation_details_path_vtable,
+        [UNIT_TIMER] = &activation_details_timer_vtable,
 };
 
 ActivationDetails *activation_details_new(Unit *trigger_unit) {
index 5e9fe64ea9f9fc87b9402b5834a3ad7edab93d21..95ebe3876ffa428f86f2c12268de46ef3106e582 100755 (executable)
@@ -8,6 +8,9 @@ set -o pipefail
 cat >/lib/systemd/system/my.service <<EOF
 [Service]
 Type=oneshot
+ExecStartPre=sh -c 'test "\$TRIGGER_UNIT" = my.timer'
+ExecStartPre=sh -c 'test -n "\$TRIGGER_TIMER_REALTIME_USEC"'
+ExecStartPre=sh -c 'test -n "\$TRIGGER_TIMER_MONOTONIC_USEC"'
 ExecStart=/bin/echo Timer runs me
 EOF