process-util: add new pid{ref,}_get_start_time() helper

This also adds a test case that test pidref_safe_fork(), pidref_wait()
and related calls.
This commit is contained in:
Lennart Poettering
2024-01-02 17:57:34 +01:00
parent f17132260f
commit 3dee63b762
3 changed files with 99 additions and 0 deletions
+76
View File
@@ -730,6 +730,82 @@ int get_process_ppid(pid_t pid, pid_t *ret) {
return 0;
}
int pid_get_start_time(pid_t pid, uint64_t *ret) {
_cleanup_free_ char *line = NULL;
const char *p;
int r;
assert(pid >= 0);
p = procfs_file_alloca(pid, "stat");
r = read_one_line_file(p, &line);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
/* Let's skip the pid and comm fields. The latter is enclosed in () but does not escape any () in its
* value, so let's skip over it manually */
p = strrchr(line, ')');
if (!p)
return -EIO;
p++;
unsigned long llu;
if (sscanf(p, " "
"%*c " /* state */
"%*u " /* ppid */
"%*u " /* pgrp */
"%*u " /* session */
"%*u " /* tty_nr */
"%*u " /* tpgid */
"%*u " /* flags */
"%*u " /* minflt */
"%*u " /* cminflt */
"%*u " /* majflt */
"%*u " /* cmajflt */
"%*u " /* utime */
"%*u " /* stime */
"%*u " /* cutime */
"%*u " /* cstime */
"%*i " /* priority */
"%*i " /* nice */
"%*u " /* num_threads */
"%*u " /* itrealvalue */
"%lu ", /* starttime */
&llu) != 1)
return -EIO;
if (ret)
*ret = llu;
return 0;
}
int pidref_get_start_time(const PidRef *pid, uint64_t *ret) {
uint64_t t;
int r;
if (!pidref_is_set(pid))
return -ESRCH;
r = pid_get_start_time(pid->pid, ret ? &t : NULL);
if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (ret)
*ret = t;
return 0;
}
int get_process_umask(pid_t pid, mode_t *ret) {
_cleanup_free_ char *m = NULL;
const char *p;
+2
View File
@@ -54,6 +54,8 @@ int get_process_cwd(pid_t pid, char **ret);
int get_process_root(pid_t pid, char **ret);
int get_process_environ(pid_t pid, char **ret);
int get_process_ppid(pid_t pid, pid_t *ret);
int pid_get_start_time(pid_t pid, uint64_t *ret);
int pidref_get_start_time(const PidRef* pid, uint64_t *ret);
int get_process_umask(pid_t pid, mode_t *ret);
int container_get_leader(const char *machine, pid_t *pid);
+21
View File
@@ -946,6 +946,27 @@ TEST(is_reaper_process) {
}
}
TEST(pid_get_start_time) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
assert_se(pidref_set_self(&pidref) >= 0);
uint64_t start_time;
assert_se(pidref_get_start_time(&pidref, &start_time) >= 0);
log_info("our starttime: %" PRIu64, start_time);
_cleanup_(pidref_done_sigkill_wait) PidRef child = PIDREF_NULL;
assert_se(pidref_safe_fork("(stub)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &child) >= 0);
uint64_t start_time2;
assert_se(pidref_get_start_time(&child, &start_time2) >= 0);
log_info("child starttime: %" PRIu64, start_time2);
assert_se(start_time2 >= start_time);
}
static int intro(void) {
log_show_color(true);
return EXIT_SUCCESS;