summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS13
-rw-r--r--man/org.freedesktop.systemd1.xml34
-rw-r--r--src/core/dbus-execute.h2
-rw-r--r--src/core/execute.c19
-rw-r--r--src/core/execute.h7
-rw-r--r--src/core/service.c30
-rwxr-xr-xtest/units/testsuite-07.exec-timestamps.sh6
7 files changed, 74 insertions, 37 deletions
diff --git a/NEWS b/NEWS
index e587ade01f..ac7f0f1154 100644
--- a/NEWS
+++ b/NEWS
@@ -198,13 +198,12 @@ CHANGES WITH 256-rc1:
PID 1 will start to have the effect of shutting down the system
cleanly).
- * New D-Bus properties ExecMainHandoverTimestamp and
- ExecMainHandoverTimestampMonotonic are now published by services of
- type exec, dbus, notify, and notify-reload.
- This timestamp is taken as the very last operation before executing
- a service's binary, which allows users to accurately track when
- execution control of the process is handed over from systemd to the
- payload.
+ * New D-Bus properties ExecMainHandoffTimestamp and
+ ExecMainHandoffTimestampMonotonic are now published by services
+ units. This timestamp is taken as the very last operation before
+ handing off control to invoked binaries. This information is
+ available for other unit types that fork off processes (i.e. mount,
+ swap, socket units), but currently only via "systemd-analyze dump".
Journal:
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index ca8696bed5..9e29eda4e0 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -2766,8 +2766,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly t ExecMainStartTimestampMonotonic = ...;
readonly t ExecMainExitTimestamp = ...;
readonly t ExecMainExitTimestampMonotonic = ...;
- readonly t ExecMainHandoverTimestamp = ...;
- readonly t ExecMainHandoverTimestampMonotonic = ...;
+ readonly t ExecMainHandoffTimestamp = ...;
+ readonly t ExecMainHandoffTimestampMonotonic = ...;
readonly u ExecMainPID = ...;
readonly i ExecMainCode = ...;
readonly i ExecMainStatus = ...;
@@ -4057,9 +4057,9 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainExitTimestampMonotonic"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ExecMainHandoverTimestamp"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecMainHandoffTimestamp"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ExecMainHandoverTimestampMonotonic"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ExecMainHandoffTimestampMonotonic"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainPID"/>
@@ -4710,18 +4710,20 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<para><varname>ExecMainStartTimestamp</varname>, <varname>ExecMainStartTimestampMonotonic</varname>,
<varname>ExecMainExitTimestamp</varname>, <varname>ExecMainExitTimestampMonotonic</varname>,
- <varname>ExecMainHandoverTimestamp</varname>, <varname>ExecMainHandoverTimestampMonotonic</varname>,
+ <varname>ExecMainHandoffTimestamp</varname>, <varname>ExecMainHandoffTimestampMonotonic</varname>,
<varname>ExecMainPID</varname>, <varname>ExecMainCode</varname>, <varname>ExecMainStatus</varname>
contain information about the main process of the service as far as it is known. The
- <varname>ExecMainStartTimestamp</varname> timestamps record when the main child process is spawned by
- the service manager. <varname>ExecMainExitTimestamp</varname> timestamps record when the main child
- process exit has been detected by the service manager. <varname>ExecMainHandoverTimestamp</varname>
- timestamps record when the service executable is executed by <command>systemd-executor</command> for
- services of type <literal>exec</literal>, <literal>dbus</literal>, <literal>notify</literal>, and
- <literal>notify-reload</literal>. This is often the same runtime information that is stored in
- <varname>ExecStart=</varname>. However, it deviates for <varname>Type=forking</varname> services where
- the main process of the service is not forked off systemd directly. These fields either contain
- information of the last run of the process or of the current running process.</para>
+ <varname>ExecMainStartTimestamp</varname> timestamps record when the main process of the service is
+ created. <varname>ExecMainExitTimestamp</varname> timestamps record when the main process exit has been
+ detected by the service manager. <varname>ExecMainHandoffTimestamp</varname> timestamps records when
+ the service binary is about to be executed by <command>systemd-executor</command> (this timestamp is
+ recorded regardless if the immediately following <function>execve()</function> system call succeeds or
+ fails). This is often the same runtime information that is also maintained for
+ <varname>ExecStart=</varname>. However, it deviates for services with <varname>Type=forking</varname>
+ as well as services that use <varname>MAINPID=</varname> <function>sd_notify()</function> messages as
+ the main process of the service is not forked off by the service manager directly in that case. These
+ fields either contain information of the last run of the process or of the current running
+ process.</para>
<para><varname>MainPID</varname> and <varname>ControlPID</varname> contain the main and control PID of
the service. The main PID is the current main PID of the service and is 0 when the service currently
@@ -12067,8 +12069,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>EffectiveMemoryMax</varname>,
<varname>EffectiveTasksMax</varname>,
<varname>MemoryZSwapWriteback</varname>,
- <varname>ExecMainHandoverTimestampMonotonic</varname>, and
- <varname>ExecMainHandoverTimestamp</varname> were added in version 256.</para>
+ <varname>ExecMainHandoffTimestampMonotonic</varname>, and
+ <varname>ExecMainHandoffTimestamp</varname> were added in version 256.</para>
</refsect2>
<refsect2>
<title>Socket Unit Objects</title>
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
index a1205b0997..4b7cb86d3e 100644
--- a/src/core/dbus-execute.h
+++ b/src/core/dbus-execute.h
@@ -9,7 +9,7 @@
#define BUS_EXEC_STATUS_VTABLE(prefix, offset, flags) \
BUS_PROPERTY_DUAL_TIMESTAMP(prefix "StartTimestamp", (offset) + offsetof(ExecStatus, start_timestamp), flags), \
BUS_PROPERTY_DUAL_TIMESTAMP(prefix "ExitTimestamp", (offset) + offsetof(ExecStatus, exit_timestamp), flags), \
- BUS_PROPERTY_DUAL_TIMESTAMP(prefix "HandoverTimestamp", (offset) + offsetof(ExecStatus, handover_timestamp), flags), \
+ BUS_PROPERTY_DUAL_TIMESTAMP(prefix "HandoffTimestamp", (offset) + offsetof(ExecStatus, handoff_timestamp), flags), \
SD_BUS_PROPERTY(prefix "PID", "u", bus_property_get_pid, (offset) + offsetof(ExecStatus, pid), flags), \
SD_BUS_PROPERTY(prefix "Code", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, code), flags), \
SD_BUS_PROPERTY(prefix "Status", "i", bus_property_get_int, (offset) + offsetof(ExecStatus, status), flags)
diff --git a/src/core/execute.c b/src/core/execute.c
index 26a4bf1b6f..7528629739 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1842,6 +1842,19 @@ void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int
(void) utmp_put_dead_process(context->utmp_id, pid, code, status);
}
+void exec_status_handoff(ExecStatus *s, const struct ucred *ucred, const dual_timestamp *ts) {
+ assert(s);
+ assert(ucred);
+ assert(ts);
+
+ if (ucred->pid != s->pid)
+ *s = (ExecStatus) {
+ .pid = ucred->pid,
+ };
+
+ s->handoff_timestamp = *ts;
+}
+
void exec_status_reset(ExecStatus *s) {
assert(s);
@@ -1866,10 +1879,10 @@ void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix) {
"%sStart Timestamp: %s\n",
prefix, FORMAT_TIMESTAMP(s->start_timestamp.realtime));
- if (dual_timestamp_is_set(&s->handover_timestamp))
+ if (dual_timestamp_is_set(&s->handoff_timestamp))
fprintf(f,
- "%sHandover Timestamp: %s\n",
- prefix, FORMAT_TIMESTAMP(s->handover_timestamp.realtime));
+ "%sHandoff Timestamp: %s\n",
+ prefix, FORMAT_TIMESTAMP(s->handoff_timestamp.realtime));
if (dual_timestamp_is_set(&s->exit_timestamp))
fprintf(f,
diff --git a/src/core/execute.h b/src/core/execute.h
index 202ef5f82b..6a313640de 100644
--- a/src/core/execute.h
+++ b/src/core/execute.h
@@ -91,7 +91,7 @@ typedef enum ExecKeyringMode {
struct ExecStatus {
dual_timestamp start_timestamp;
dual_timestamp exit_timestamp;
- dual_timestamp handover_timestamp;
+ dual_timestamp handoff_timestamp;
pid_t pid;
int code; /* as in siginfo_t::si_code */
int status; /* as in siginfo_t::si_status */
@@ -444,9 +444,7 @@ struct ExecParameters {
int stdout_fd;
int stderr_fd;
- /* An fd that is closed by the execve(), and thus will result in EOF when the execve() is done. It
- * will also be used to send a timestamp taken as the very last operation before execve, for
- * tracking purposes. */
+ /* An fd that is closed by the execve(), and thus will result in EOF when the execve() is done. */
int exec_fd;
char *notify_socket;
@@ -547,6 +545,7 @@ char** exec_context_get_restrict_filesystems(const ExecContext *c);
void exec_status_start(ExecStatus *s, pid_t pid);
void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status);
+void exec_status_handoff(ExecStatus *s, const struct ucred *ucred, const dual_timestamp *ts);
void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix);
void exec_status_reset(ExecStatus *s);
diff --git a/src/core/service.c b/src/core/service.c
index 4a512fd24b..b3fe2c0b1f 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3009,7 +3009,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
(void) serialize_item_format(f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
(void) serialize_dual_timestamp(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
(void) serialize_dual_timestamp(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
- (void) serialize_dual_timestamp(f, "main-exec-status-handover", &s->main_exec_status.handover_timestamp);
+ (void) serialize_dual_timestamp(f, "main-exec-status-handoff", &s->main_exec_status.handoff_timestamp);
if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) {
(void) serialize_item_format(f, "main-exec-status-code", "%i", s->main_exec_status.code);
@@ -3294,8 +3294,8 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp);
else if (streq(key, "main-exec-status-exit"))
deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp);
- else if (streq(key, "main-exec-status-handover"))
- deserialize_dual_timestamp(value, &s->main_exec_status.handover_timestamp);
+ else if (streq(key, "main-exec-status-handoff"))
+ deserialize_dual_timestamp(value, &s->main_exec_status.handoff_timestamp);
else if (streq(key, "notify-access-override")) {
NotifyAccess notify_access;
@@ -4578,6 +4578,29 @@ static void service_notify_message(
unit_add_to_dbus_queue(u);
}
+static void service_handoff_timestamp(
+ Unit *u,
+ const struct ucred *ucred,
+ const dual_timestamp *ts) {
+
+ Service *s = ASSERT_PTR(SERVICE(u));
+
+ assert(ucred);
+ assert(ts);
+
+ if (s->main_pid.pid == ucred->pid) {
+ if (s->main_command)
+ exec_status_handoff(&s->main_command->exec_status, ucred, ts);
+
+ exec_status_handoff(&s->main_exec_status, ucred, ts);
+ } else if (s->control_pid.pid == ucred->pid && s->control_command)
+ exec_status_handoff(&s->control_command->exec_status, ucred, ts);
+ else
+ return;
+
+ unit_add_to_dbus_queue(u);
+}
+
static int service_get_timeout(Unit *u, usec_t *timeout) {
Service *s = ASSERT_PTR(SERVICE(u));
uint64_t t;
@@ -5163,6 +5186,7 @@ const UnitVTable service_vtable = {
.notify_cgroup_empty = service_notify_cgroup_empty_event,
.notify_cgroup_oom = service_notify_cgroup_oom_event,
.notify_message = service_notify_message,
+ .notify_handoff_timestamp = service_handoff_timestamp,
.main_pid = service_main_pid,
.control_pid = service_control_pid,
diff --git a/test/units/testsuite-07.exec-timestamps.sh b/test/units/testsuite-07.exec-timestamps.sh
index 799bc89e06..0211166ae3 100755
--- a/test/units/testsuite-07.exec-timestamps.sh
+++ b/test/units/testsuite-07.exec-timestamps.sh
@@ -8,10 +8,10 @@ set -o pipefail
systemd-run --service-type notify --property NotifyAccess=all --unit notify.service --wait sh -c 'systemd-notify --ready; exit 1' || :
start=$(systemctl show --property=ExecMainStartTimestampMonotonic --value notify.service)
-handover=$(systemctl show --property=ExecMainHandoverTimestampMonotonic --value notify.service)
+handoff=$(systemctl show --property=ExecMainHandoffTimestampMonotonic --value notify.service)
active=$(systemctl show --property=ActiveEnterTimestampMonotonic --value notify.service)
exit=$(systemctl show --property=ExecMainExitTimestampMonotonic --value notify.service)
-[[ $start -le $handover ]]
-[[ $handover -le $active ]]
+[[ $start -le $handoff ]]
+[[ $handoff -le $active ]]
[[ $active -le $exit ]]