mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 10:43:35 +08:00
service: set TRIGGER_UNIT= and TRIGGER_TIMER_REALTIME_USEC/MONOTONIC_USEC on activation by timer unit
Same as path unit, best effort.
This commit is contained in:
parent
4c42032854
commit
c8bc7519c8
@ -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.
|
||||
|
@ -366,6 +366,10 @@
|
||||
|
||||
<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>,
|
||||
|
107
src/core/timer.c
107
src/core/timer.c
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user