_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
_cleanup_fdset_free_ FDSet *fdset = NULL;
_cleanup_fclose_ FILE *f = NULL;
+ dual_timestamp start_timestamp;
int r;
assert(unit);
xsprintf(serialization_fd_number, "%i", fileno(f));
+ /* Record the start timestamp before we fork so that it is guaranteed to be earlier than the
+ * handoff timestamp. */
+ dual_timestamp_now(&start_timestamp);
+
/* The executor binary is pinned, to avoid compatibility problems during upgrades. */
r = posix_spawn_wrapper(
FORMAT_PROC_FD_PATH(unit->manager->executor_fd),
log_unit_debug(unit, "Forked %s as " PID_FMT " (%s CLONE_INTO_CGROUP)",
command->path, pidref.pid, r > 0 ? "via" : "without");
- exec_status_start(&command->exec_status, pidref.pid);
+ exec_status_start(&command->exec_status, pidref.pid, &start_timestamp);
*ret = TAKE_PIDREF(pidref);
return 0;
return l ? TAKE_PTR(l) : strv_new(NULL);
}
-void exec_status_start(ExecStatus *s, pid_t pid) {
+void exec_status_start(ExecStatus *s, pid_t pid, const dual_timestamp *ts) {
assert(s);
*s = (ExecStatus) {
.pid = pid,
};
- dual_timestamp_now(&s->start_timestamp);
+ if (ts)
+ s->start_timestamp = *ts;
+ else
+ dual_timestamp_now(&s->start_timestamp);
}
void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status) {
s->pid_file_pathspec = mfree(s->pid_file_pathspec);
}
-static int service_set_main_pidref(Service *s, PidRef pidref_consume) {
+static int service_set_main_pidref(Service *s, PidRef pidref_consume, const dual_timestamp *start_timestamp) {
_cleanup_(pidref_done) PidRef pidref = pidref_consume;
int r;
if (!pidref_equal(&s->main_pid, &pidref)) {
service_unwatch_main_pid(s);
- exec_status_start(&s->main_exec_status, pidref.pid);
+ exec_status_start(&s->main_exec_status, pidref.pid, start_timestamp);
}
s->main_pid = TAKE_PIDREF(pidref);
} else
log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pidref.pid);
- r = service_set_main_pidref(s, TAKE_PIDREF(pidref));
+ r = service_set_main_pidref(s, TAKE_PIDREF(pidref), /* start_timestamp = */ NULL);
if (r < 0)
return r;
return;
log_unit_debug(UNIT(s), "Main PID guessed: "PID_FMT, pid.pid);
- if (service_set_main_pidref(s, TAKE_PIDREF(pid)) < 0)
+ if (service_set_main_pidref(s, TAKE_PIDREF(pid), /* start_timestamp = */ NULL) < 0)
return;
r = unit_watch_pidref(UNIT(s), &s->main_pid, /* exclusive= */ false);
/* For simple services we immediately start
* the START_POST binaries. */
- (void) service_set_main_pidref(s, TAKE_PIDREF(pidref));
+ (void) service_set_main_pidref(s, TAKE_PIDREF(pidref), &c->exec_status.start_timestamp);
service_enter_start_post(s);
} else if (s->type == SERVICE_FORKING) {
/* For D-Bus services we know the main pid right away, but wait for the bus name to appear on the
* bus. 'notify' and 'exec' services are similar. */
- (void) service_set_main_pidref(s, TAKE_PIDREF(pidref));
+ (void) service_set_main_pidref(s, TAKE_PIDREF(pidref), &c->exec_status.start_timestamp);
service_set_state(s, SERVICE_START);
} else
assert_not_reached();
return;
}
- (void) service_set_main_pidref(s, TAKE_PIDREF(pidref));
+ (void) service_set_main_pidref(s, TAKE_PIDREF(pidref), &s->main_command->exec_status.start_timestamp);
}
static int service_start(Unit *u) {
PidRef pidref;
if (!pidref_is_set(&s->main_pid) && deserialize_pidref(fds, value, &pidref) >= 0)
- (void) service_set_main_pidref(s, pidref);
+ (void) service_set_main_pidref(s, pidref, /* start_timestamp = */ NULL);
} else if (streq(key, "main-pid-known")) {
int b;
log_unit_warning(u, "New main PID "PID_FMT" does not belong to service, refusing.", new_main_pid.pid);
}
if (r > 0) {
- (void) service_set_main_pidref(s, TAKE_PIDREF(new_main_pid));
+ (void) service_set_main_pidref(s, TAKE_PIDREF(new_main_pid), /* start_timestamp = */ NULL);
r = unit_watch_pidref(UNIT(s), &s->main_pid, /* exclusive= */ false);
if (r < 0)
log_unit_debug(UNIT(s), "D-Bus name %s is now owned by process " PID_FMT, s->bus_name, pidref.pid);
- (void) service_set_main_pidref(s, TAKE_PIDREF(pidref));
+ (void) service_set_main_pidref(s, TAKE_PIDREF(pidref), /* start_timestamp = */ NULL);
(void) unit_watch_pidref(UNIT(s), &s->main_pid, /* exclusive= */ false);
return 1;
}