Make fractional delays for top(1) work for interactive mode.

In r334906, the -s option was changed to allow fractional times, but
this only functioned correctly for batch mode.  In interactive mode, any
delay below 1.0 would get floored to zero.  This would put top(1) into a
tight loop, which could be difficult to interrupt.

Fix this by storing the -s option value (after validation) into a struct
timeval, and using that struct consistently for delaying with select(2).

Next up is to allow interactive entry of a fractional delay value.

MFC after:	3 days
This commit is contained in:
dim 2019-09-27 20:20:21 +00:00
parent db240be427
commit 0457e6c24d
2 changed files with 28 additions and 24 deletions

View File

@ -147,7 +147,7 @@ no information is available about the percentage of time spent by the CPU in eve
.It Fl s Ar time
Set the delay between screen updates to
.Ar time
seconds.
seconds, which may be fractional.
The default delay between updates is 1 second.
.It Fl o Ar field
Sort the process display area on the specified field.

View File

@ -233,7 +233,7 @@ main(int argc, const char *argv[])
static char tempbuf2[50];
sigset_t old_sigmask, new_sigmask;
int topn = Infinity;
double delay = 2;
struct timeval delay = { 2, 0 };
int displays = 0; /* indicates unspecified */
int sel_ret = 0;
time_t curr_time;
@ -378,19 +378,25 @@ main(int argc, const char *argv[])
}
case 's':
delay = strtod(optarg, &nptr);
if (nptr == optarg) {
{
double delay_d = strtod(optarg, &nptr);
if (nptr == optarg)
{
warnx("warning: invalid delay");
delay = 2;
warnings++;
}
if (delay < 0) {
else if (delay_d <= 0)
{
warnx("warning: seconds delay should be positive -- using default");
delay = 2;
warnings++;
}
else
{
delay.tv_sec = delay_d;
delay.tv_usec = (delay_d - delay.tv_sec) * 1e6;
}
break;
}
case 'q': /* be quick about it */
errno = 0;
@ -704,7 +710,8 @@ main(int argc, const char *argv[])
no_command = true;
if (!interactive)
{
usleep(delay * 1e6);
timeout = delay;
select(0, NULL, NULL, NULL, &timeout);
if (leaveflag) {
end_screen();
exit(0);
@ -718,8 +725,7 @@ main(int argc, const char *argv[])
/* set up arguments for select with timeout */
FD_ZERO(&readfds);
FD_SET(0, &readfds); /* for standard input */
timeout.tv_sec = delay;
timeout.tv_usec = 0;
timeout = delay;
if (leaveflag) {
end_screen();
@ -880,12 +886,10 @@ main(int argc, const char *argv[])
case CMD_delay: /* new seconds delay */
new_message(MT_standout, "Seconds to delay: ");
if ((i = readline(tempbuf1, 8, true)) > -1)
if ((i = readline(tempbuf1, 8, true)) > 0)
{
if ((delay = i) == 0)
{
delay = 1;
}
delay.tv_sec = i;
delay.tv_usec = 0;
}
clear_message();
break;