From owner-svn-src-all@freebsd.org Wed Dec 9 18:07:27 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 98C269D5EFA; Wed, 9 Dec 2015 18:07:27 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 737E61736; Wed, 9 Dec 2015 18:07:27 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tB9I7QwF069316; Wed, 9 Dec 2015 18:07:26 GMT (envelope-from asomers@FreeBSD.org) Received: (from asomers@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tB9I7QEt069315; Wed, 9 Dec 2015 18:07:26 GMT (envelope-from asomers@FreeBSD.org) Message-Id: <201512091807.tB9I7QEt069315@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: asomers set sender to asomers@FreeBSD.org using -f From: Alan Somers Date: Wed, 9 Dec 2015 18:07:26 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292019 - head/usr.sbin/iostat X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Dec 2015 18:07:27 -0000 Author: asomers Date: Wed Dec 9 18:07:26 2015 New Revision: 292019 URL: https://svnweb.freebsd.org/changeset/base/292019 Log: When iostat(8) receives SIGINT while running with "-w" or "-c", it will now print statistics one more time before exiting. Also, it now implements the wait using setitimer instead of sleep, so the waits will be more consistent when the system is heavily loaded. MFC after: 4 weeks Sponsored by: Spectra Logic Corp Differential Revision: https://reviews.freebsd.org/D4473 Modified: head/usr.sbin/iostat/iostat.c Modified: head/usr.sbin/iostat/iostat.c ============================================================================== --- head/usr.sbin/iostat/iostat.c Wed Dec 9 13:45:51 2015 (r292018) +++ head/usr.sbin/iostat/iostat.c Wed Dec 9 18:07:26 2015 (r292019) @@ -110,6 +110,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +136,8 @@ struct device_selection *dev_select; int maxshowdevs; volatile sig_atomic_t headercount; volatile sig_atomic_t wresized; /* Tty resized, when non-zero. */ +volatile sig_atomic_t alarm_rang; +volatile sig_atomic_t return_requested; unsigned short wrows; /* Current number of tty rows. */ int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0; int xflag = 0, zflag = 0; @@ -143,6 +146,8 @@ int xflag = 0, zflag = 0; static void usage(void); static void needhdr(int signo); static void needresize(int signo); +static void needreturn(int signo); +static void alarm_clock(int signo); static void doresize(void); static void phdr(void); static void devstats(int perf_select, long double etime, int havelast); @@ -172,6 +177,7 @@ main(int argc, char **argv) int count = 0, waittime = 0; char *memf = NULL, *nlistf = NULL; struct devstat_match *matches; + struct itimerval alarmspec; int num_matches = 0; char errbuf[_POSIX2_LINE_MAX]; kvm_t *kd = NULL; @@ -442,10 +448,28 @@ main(int argc, char **argv) wrows = IOSTAT_DEFAULT_ROWS; } + /* + * Register a SIGINT handler so that we can print out final statistics + * when we get that signal + */ + (void)signal(SIGINT, needreturn); + + /* + * Register a SIGALRM handler to implement sleeps if the user uses the + * -c or -w options + */ + (void)signal(SIGALRM, alarm_clock); + alarmspec.it_interval.tv_sec = waittime / 1000; + alarmspec.it_interval.tv_usec = 1000 * (waittime % 1000); + alarmspec.it_value.tv_sec = waittime / 1000; + alarmspec.it_value.tv_usec = 1000 * (waittime % 1000); + setitimer(ITIMER_REAL, &alarmspec, NULL); + for (headercount = 1;;) { struct devinfo *tmp_dinfo; long tmp; long double etime; + sigset_t sigmask, oldsigmask; if (Tflag > 0) { if ((readvar(kd, "kern.tty_nin", X_TTY_NIN, &cur.tk_nin, @@ -599,10 +623,23 @@ main(int argc, char **argv) } fflush(stdout); - if (count >= 0 && --count <= 0) + if ((count >= 0 && --count <= 0) || return_requested) break; - usleep(waittime * 1000); + /* + * Use sigsuspend to safely sleep until either signal is + * received + */ + alarm_rang = 0; + sigemptyset(&sigmask); + sigaddset(&sigmask, SIGINT); + sigaddset(&sigmask, SIGALRM); + sigprocmask(SIG_BLOCK, &sigmask, &oldsigmask); + while (! (alarm_rang || return_requested) ) { + sigsuspend(&oldsigmask); + } + sigprocmask(SIG_UNBLOCK, &sigmask, NULL); + havelast = 1; } @@ -633,6 +670,24 @@ needresize(int signo) } /* + * Record the alarm so the main loop can break its sleep + */ +void +alarm_clock(int signo) +{ + alarm_rang = 1; +} + +/* + * Request that the main loop exit soon + */ +void +needreturn(int signo) +{ + return_requested = 1; +} + +/* * Update the global `wrows' count of terminal rows. */ void