On Thu, Sep 17, 2020 at 06:29:48PM -0500, Scott Cheloha wrote:
> [...]
> 
> Using nanosleep(2) to print the stats periodically causes the period
> to drift.  If you use setitimer(2) it won't drift.
> 
> ok?

19 month bump and rebase.

I have updated the patch according to input from kn@.

Once again, using nanosleep(2) here to print the stats periodically is
flawed.  The period will drift.  Using setitimer(2)/sigsuspend(2) is
better.

While here:

- We don't need the hundred million second upper bound anymore.  Just
  cap the wait at UINT_MAX seconds.

- Use the idiomatic strtonum(3) error message format, it works here.

ok?

Index: kstat.c
===================================================================
RCS file: /cvs/src/usr.bin/kstat/kstat.c,v
retrieving revision 1.9
diff -u -p -r1.9 kstat.c
--- kstat.c     22 Apr 2022 00:29:20 -0000      1.9
+++ kstat.c     29 Apr 2022 01:43:31 -0000
@@ -15,6 +15,8 @@
  */
 
 #include <ctype.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.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 *,
@@ -134,16 +137,17 @@ main(int argc, char *argv[])
        int fd;
        const char *errstr;
        int ch;
-       struct timespec interval = { 0, 0 };
+       struct itimerval itv;
+       unsigned int wait = 0;
+       sigset_t empty;
        int i;
 
        while ((ch = getopt(argc, argv, "w:")) != -1) {
                switch (ch) {
                case 'w':
-                       interval.tv_sec = strtonum(optarg, 1, 100000000,
-                           &errstr);
+                       wait = strtonum(optarg, 1, UINT_MAX, &errstr);
                        if (errstr != NULL)
-                               errx(1, "wait %s: %s", optarg, errstr);
+                               errx(1, "wait is %s: %s", errstr, optarg);
                        break;
                default:
                        usage();
@@ -165,15 +169,21 @@ main(int argc, char *argv[])
        if (ioctl(fd, KSTATIOC_VERSION, &version) == -1)
                err(1, "kstat version");
 
-       kstat_list(&kt, fd, version, &kfs);
-       kstat_print(&kt);
-
-       if (interval.tv_sec == 0)
+       if (wait == 0) {
+               kstat_list(&kt, fd, version, &kfs);
+               kstat_print(&kt);
                return (0);
+       }
 
+       sigemptyset(&empty);
+       signal(SIGALRM, handle_alrm);
+       itv.it_value.tv_sec = wait;
+       itv.it_value.tv_usec = 0;
+       itv.it_interval = itv.it_value;
+       if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
+               err(1, "setitimer");
        for (;;) {
-               nanosleep(&interval, NULL);
-
+               sigsuspend(&empty);
                kstat_read(&kt, fd);
                kstat_print(&kt);
        }
@@ -547,4 +557,9 @@ kstat_read(struct kstat_tree *kt, int fd
                if (ioctl(fd, KSTATIOC_FIND_ID, ksreq) == -1)
                        err(1, "update id %llu", ksreq->ks_id);
        }
+}
+
+static void
+handle_alrm(int signo)
+{
 }

Reply via email to