Hi,

Because the system clock can jump around, process start times
should be recorded as offsets from boot and only converted to
a time of day on request.

This keeps ps(1)'s etime accurate and ensures processes are
correctly sorted by age in ps(1) and pgrep(1).

I don't think we're losing much by declining to preserve the
time of day when the process forked.

FreeBSD has made this change, though NetBSD has not.

The attached patch isn't perfect, as there remains a small window
after kvm_getprocs is called where the system clock can jump again.
To circumvent that we'd need to compute the elapsed real time for
the process in the kernel, or pass out ps_start alongside the derived
time of day and let userspace compute the elapsed realtime with
the CLOCK_BOOTTIME clock.  Unsure how people feel about extending
kinfo_proc, though.

This change doesn't require any userspace recompilation for inspecting
a live kernel: on reboot -lkvm binaries behave as expected.

I'm pretty sure this will require changes to libkvm to fix up the start
time when inspecting a dead kernel, but I can't figure out how to core my
own system so I can test said changes.

Thoughts?  Help creating a core for test?

--
Scott Cheloha

Index: sys/kern/init_main.c
===================================================================
RCS file: /cvs/src/sys/kern/init_main.c,v
retrieving revision 1.277
diff -u -p -r1.277 init_main.c
--- sys/kern/init_main.c        28 Apr 2018 03:13:04 -0000      1.277
+++ sys/kern/init_main.c        5 Jun 2018 16:43:08 -0000
@@ -512,7 +512,7 @@ main(void *framep)
         */
        nanotime(&boottime);
        LIST_FOREACH(pr, &allprocess, ps_list) {
-               pr->ps_start = boottime;
+               getnanouptime(&pr->ps_start);
                TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
                        nanouptime(&p->p_cpu->ci_schedstate.spc_runtime);
                        timespecclear(&p->p_rtime);
Index: sys/kern/kern_acct.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_acct.c,v
retrieving revision 1.36
diff -u -p -r1.36 kern_acct.c
--- sys/kern/kern_acct.c        28 Apr 2018 03:13:04 -0000      1.36
+++ sys/kern/kern_acct.c        5 Jun 2018 16:43:08 -0000
@@ -184,8 +184,8 @@ acct_process(struct proc *p)
        acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_nsec);
 
        /* (3) The elapsed time the command ran (and its starting time) */
-       acct.ac_btime = pr->ps_start.tv_sec;
-       getnanotime(&tmp);
+       getnanouptime(&tmp);
+       acct.ac_btime = time_second - (tmp.tv_sec - pr->ps_start.tv_sec);
        timespecsub(&tmp, &pr->ps_start, &tmp);
        acct.ac_etime = encode_comp_t(tmp.tv_sec, tmp.tv_nsec);
 
Index: sys/kern/kern_fork.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.202
diff -u -p -r1.202 kern_fork.c
--- sys/kern/kern_fork.c        30 Dec 2017 20:47:00 -0000      1.202
+++ sys/kern/kern_fork.c        5 Jun 2018 16:43:08 -0000
@@ -451,7 +451,7 @@ fork1(struct proc *curp, int flags, void
        /*
         * For new processes, set accounting bits and mark as complete.
         */
-       getnanotime(&pr->ps_start);
+       getnanouptime(&pr->ps_start);
        pr->ps_acflag = AFORK;
        atomic_clearbits_int(&pr->ps_flags, PS_EMBRYO);
 
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.341
diff -u -p -r1.341 kern_sysctl.c
--- sys/kern/kern_sysctl.c      2 Jun 2018 16:38:21 -0000       1.341
+++ sys/kern/kern_sysctl.c      5 Jun 2018 16:43:08 -0000
@@ -1596,7 +1596,8 @@ fill_kproc(struct process *pr, struct ki
        struct session *s = pr->ps_session;
        struct tty *tp;
        struct vmspace *vm = pr->ps_vmspace;
-       struct timespec ut, st;
+       struct timespec elapsed, now, started, uptime;
+       struct timespec st, ut;
        int isthread;
 
        isthread = p != NULL;
@@ -1627,6 +1628,12 @@ fill_kproc(struct process *pr, struct ki
        if ((pr->ps_flags & PS_ZOMBIE) == 0) {
                if ((pr->ps_flags & PS_EMBRYO) == 0 && vm != NULL)
                        ki->p_vm_rssize = vm_resident_count(vm);
+               getnanouptime(&uptime);
+               getnanotime(&now);
+               timespecsub(&uptime, &pr->ps_start, &elapsed);
+               timespecsub(&now, &elapsed, &started);
+               ki->p_ustart_sec = started.tv_sec;
+               ki->p_ustart_usec = started.tv_nsec/1000;
                calctsru(isthread ? &p->p_tu : &pr->ps_tu, &ut, &st, NULL);
                ki->p_uutime_sec = ut.tv_sec;
                ki->p_uutime_usec = ut.tv_nsec/1000;
Index: sys/sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.248
diff -u -p -r1.248 proc.h
--- sys/sys/proc.h      12 Apr 2018 17:13:44 -0000      1.248
+++ sys/sys/proc.h      5 Jun 2018 16:43:08 -0000
@@ -228,7 +228,7 @@ struct process {
 #define ps_endcopy     ps_refcnt
        int     ps_refcnt;              /* Number of references. */
 
-       struct  timespec ps_start;      /* starting time. */
+       struct  timespec ps_start;      /* starting boot offset. */
        struct  timeout ps_realit_to;   /* real-time itimer trampoline. */
 };
 
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.177
diff -u -p -r1.177 sysctl.h
--- sys/sys/sysctl.h    26 May 2018 10:16:14 -0000      1.177
+++ sys/sys/sysctl.h    5 Jun 2018 16:43:08 -0000
@@ -516,7 +516,8 @@ struct kinfo_vmentry {
  *     sa - source struct sigacts
  * There are some members that are not handled by these macros
  * because they're too painful to generalize: p_ppid, p_sid, p_tdev,
- * p_tpgid, p_tsess, p_vm_rssize, p_u[us]time_{sec,usec}, p_cpuid
+ * p_tpgid, p_tsess, p_vm_rssize, p_u[us]time_{sec,usec}, p_cpuid,
+ * p_ustart_{sec,usec}
  */
 
 #define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x))
@@ -629,9 +630,6 @@ do {                                                        
                \
                struct timeval tv;                                      \
                                                                        \
                (kp)->p_uvalid = 1;                                     \
-                                                                       \
-               (kp)->p_ustart_sec = (pr)->ps_start.tv_sec;             \
-               (kp)->p_ustart_usec = (pr)->ps_start.tv_nsec/1000;      \
                                                                        \
                (kp)->p_uru_maxrss = (p)->p_ru.ru_maxrss;               \
                (kp)->p_uru_ixrss = (p)->p_ru.ru_ixrss;                 \

Reply via email to