Hi,

Using nanosleep(2) to print the stats periodically causes the period
to drift.  If you use setitimer(2) it won't drift.

ok?

Index: kstat.c
===================================================================
RCS file: /cvs/src/usr.bin/kstat/kstat.c,v
retrieving revision 1.6
diff -u -p -r1.6 kstat.c
--- kstat.c     13 Aug 2020 12:37:16 -0000      1.6
+++ kstat.c     17 Sep 2020 23:24:36 -0000
@@ -15,6 +15,7 @@
  */
 
 #include <ctype.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -27,6 +28,7 @@
 #include <err.h>
 #include <vis.h>
 
+#include <sys/time.h>
 #include <sys/tree.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
@@ -104,6 +106,7 @@ kstat_cmp(const struct kstat_entry *ea, 
 RBT_PROTOTYPE(kstat_tree, kstat_entry, entry, kstat_cmp);
 RBT_GENERATE(kstat_tree, kstat_entry, entry, kstat_cmp);
 
+static void    handle_alrm(int);
 static struct kstat_filter *
                kstat_filter_parse(char *);
 static int     kstat_filter_entry(struct kstat_filters *,
@@ -130,20 +133,23 @@ main(int argc, char *argv[])
 {
        struct kstat_filters kfs = TAILQ_HEAD_INITIALIZER(kfs);
        struct kstat_tree kt = RBT_INITIALIZER();
+       struct itimerval itv;
+       time_t interval;
        unsigned int version;
+       sigset_t empty;
        int fd;
        const char *errstr;
        int ch;
-       struct timespec interval = { 0, 0 };
        int i;
 
+       interval = 0;
+
        while ((ch = getopt(argc, argv, "w:")) != -1) {
                switch (ch) {
                case 'w':
-                       interval.tv_sec = strtonum(optarg, 1, 100000000,
-                           &errstr);
+                       interval = strtonum(optarg, 1, 100000000, &errstr);
                        if (errstr != NULL)
-                               errx(1, "wait %s: %s", optarg, errstr);
+                               errx(1, "wait is %s: %s", optarg, errstr);
                        break;
                default:
                        usage();
@@ -168,17 +174,31 @@ main(int argc, char *argv[])
        kstat_list(&kt, fd, version, &kfs);
        kstat_print(&kt);
 
-       if (interval.tv_sec == 0)
+       if (interval == 0)
                return (0);
 
-       for (;;) {
-               nanosleep(&interval, NULL);
+       signal(SIGALRM, handle_alrm);
+       sigemptyset(&empty);
+
+       itv.it_value.tv_sec = interval;
+       itv.it_value.tv_usec = 0;
+       itv.it_interval = itv.it_value;
+       if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
+               err(1, "setitimer");
 
+       for (;;) {
+               sigsuspend(&empty);
                kstat_read(&kt, fd);
                kstat_print(&kt);
        }
 
        return (0);
+}
+
+static void
+handle_alrm(int signo)
+{
+       return;
 }
 
 static struct kstat_filter *

Reply via email to