diff options
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | man/org.freedesktop.systemd1.xml | 34 | ||||
-rw-r--r-- | src/core/dbus-execute.h | 2 | ||||
-rw-r--r-- | src/core/execute.c | 19 | ||||
-rw-r--r-- | src/core/execute.h | 7 | ||||
-rw-r--r-- | src/core/service.c | 30 | ||||
-rwxr-xr-x | test/units/testsuite-07.exec-timestamps.sh | 6 |
7 files changed, 74 insertions, 37 deletions
@@ -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 ]] |