Module Name:    src
Committed By:   dholland
Date:           Thu Nov 24 00:05:13 UTC 2016

Modified Files:
        src/usr.bin/netstat: if.c

Log Message:
Fix "sidewaysintpr", the thing that prints interface statistics in a
loop, to use signals properly. There are two copies of this code; one
uses kvm and the other uses sysctls. One copy had been updated to use
sigset_t and sigsuspend; the other was using vintage sigpause(). Sync
up the code so both use sigpause. Also, use sig_atomic_t, and block
SIGALRM when not waiting for it to avoid a small and unlikely but real
race.

Since the non-modernized copy of the code *had* for some been
modernized to use setitimer instead of just alarm(), propagate that
change to the other copy.

These copies could share more logic than they do.


To generate a diff of this commit:
cvs rdiff -u -r1.89 -r1.90 src/usr.bin/netstat/if.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/netstat/if.c
diff -u src/usr.bin/netstat/if.c:1.89 src/usr.bin/netstat/if.c:1.90
--- src/usr.bin/netstat/if.c:1.89	Thu Jul 14 20:38:20 2016
+++ src/usr.bin/netstat/if.c	Thu Nov 24 00:05:13 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.89 2016/07/14 20:38:20 christos Exp $	*/
+/*	$NetBSD: if.c,v 1.90 2016/11/24 00:05:13 dholland Exp $	*/
 
 /*
  * Copyright (c) 1983, 1988, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "from: @(#)if.c	8.2 (Berkeley) 2/21/94";
 #else
-__RCSID("$NetBSD: if.c,v 1.89 2016/07/14 20:38:20 christos Exp $");
+__RCSID("$NetBSD: if.c,v 1.90 2016/11/24 00:05:13 dholland Exp $");
 #endif
 #endif /* not lint */
 
@@ -100,7 +100,7 @@ static void intpr_sysctl(void);
 static void intpr_kvm(u_long, void (*)(const char *));
 
 struct iftot iftot[MAXIF], ip_cur, ip_old, sum_cur, sum_old;
-bool	signalled;			/* set if alarm goes off "early" */
+static sig_atomic_t signalled;		/* set when alarm goes off */
 
 static unsigned redraw_lines = 21;
 
@@ -712,7 +712,9 @@ iftot_print_sum(struct iftot *cur, struc
 __dead static void
 sidewaysintpr_sysctl(unsigned interval)
 {
+	struct itimerval it;
 	sigset_t emptyset;
+	sigset_t noalrm;
 	unsigned line;
 
 	set_lines();
@@ -724,9 +726,18 @@ sidewaysintpr_sysctl(unsigned interval)
 		exit(1);
 	}
 
-	(void)signal(SIGALRM, catchalarm);
+	sigemptyset(&emptyset);
+	sigemptyset(&noalrm);
+	sigaddset(&noalrm, SIGALRM);
+	sigprocmask(SIG_SETMASK, &noalrm, NULL);
+
 	signalled = 0;
-	(void)alarm(interval);
+	(void)signal(SIGALRM, catchalarm);
+
+	it.it_interval.tv_sec = it.it_value.tv_sec = interval;
+	it.it_interval.tv_usec = it.it_value.tv_usec = 0;
+	setitimer(ITIMER_REAL, &it, NULL);
+
 banner:
 	iftot_banner(&ip_cur);
 
@@ -749,11 +760,10 @@ loop:
 	putchar('\n');
 	fflush(stdout);
 	line++;
-	sigemptyset(&emptyset);
-	if (!signalled)
+	if (signalled == 0) {
 		sigsuspend(&emptyset);
+	}
 	signalled = 0;
-	(void)alarm(interval);
 	if (line == redraw_lines)
 		goto banner;
 	goto loop;
@@ -764,13 +774,14 @@ static void
 sidewaysintpr_kvm(unsigned interval, u_long off)
 {
 	struct itimerval it;
+	sigset_t emptyset;
+	sigset_t noalrm;
 	struct ifnet ifnet;
 	u_long firstifnet;
 	struct iftot *ip, *total;
 	unsigned line;
 	struct iftot *lastif, *sum, *interesting;
 	struct ifnet_head ifhead;	/* TAILQ_HEAD */
-	int oldmask;
 
 	set_lines();
 
@@ -806,8 +817,13 @@ sidewaysintpr_kvm(unsigned interval, u_l
 	}
 	lastif = ip;
 
+	sigemptyset(&emptyset);
+	sigemptyset(&noalrm);
+	sigaddset(&noalrm, SIGALRM);
+	sigprocmask(SIG_SETMASK, &noalrm, NULL);
+
+	signalled = 0;
 	(void)signal(SIGALRM, catchalarm);
-	signalled = false;
 
 	it.it_interval.tv_sec = it.it_value.tv_sec = interval;
 	it.it_interval.tv_usec = it.it_value.tv_usec = 0;
@@ -980,12 +996,10 @@ loop:
 	putchar('\n');
 	fflush(stdout);
 	line++;
-	oldmask = sigblock(sigmask(SIGALRM));
-	if (! signalled) {
-		sigpause(0);
+	if (signalled == 0) {
+		sigsuspend(&emptyset);
 	}
-	sigsetmask(oldmask);
-	signalled = false;
+	signalled = 0;
 	if (line == redraw_lines)
 		goto banner;
 	goto loop;

Reply via email to