Subject: Re: bin/34011: systat vmstat ignores refresh-interval argument
To: None <jdc@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,>
From: Julian Coleman <jdc@coris.org.uk>
List: netbsd-bugs
Date: 07/24/2006 21:25:02
The following reply was made to PR bin/34011; it has been noted by GNATS.
From: Julian Coleman <jdc@coris.org.uk>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: bin/34011: systat vmstat ignores refresh-interval argument
Date: Mon, 24 Jul 2006 22:21:10 +0100
> 26 seconds is the boundary where trouble starts (updates more
> than once a second) Does 256 ring a bell here? The function
> used is "timeout(millisecs)" from curses. The manual mentions
> no restriction on the number of millisecs supported. The limit
> is likely to be around 25600 millisecs as 26000 seems to fail.
> A short look into lib/libcurses/timeout.c shows that it is the
> VTIME parameter(char!) of the termios interface - thus the systat
> implementation will currently be able to sensibly sleep 1-25 secs.
> For the curious: Above that the sleep time wraps to <secs-26>.4 s
> for 26-51 secs then +0.8, +0.2, +0.6, +0.0. But that is not useful
> unless you want the fast updates :-)
>
> Looks either like a doc bug or some more SMOP to get it o match
> users expectations.
Thanks for pointing this out. This is indeed the problem. Checking on a
Solaris machine with the attached test, the maximum timeout is ~25 seconds.
The attached patches make any delay above 25500ms into 25.5s and also fix a
bug where calling notimeout() after calling timeout() was broken. However,
this latter fix is not ideal, as we will call tcsetattr() every time we
call getch(). I'll produce a proper fix shortly (hopefully later in the
week).
J
- - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
#include <curses.h>
#include <time.h>
int
main ()
{
time_t st, et;
initscr();
printw("Start\n");
timeout(40000);
st = time(NULL);
getch();
et = time(NULL);
printw("End (%ld)\n", et - st);
timeout(-1);
getch();
endwin();
}
- - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
diff -ur /usr/src/lib/libcurses/curses_input.3 ./curses_input.3
--- /usr/src/lib/libcurses/curses_input.3 2004-12-16 16:41:43.000000000 +0000
+++ ./curses_input.3 2006-07-24 22:03:12.000000000 +0100
@@ -334,6 +334,9 @@
will be returned.
Note that for a positive number, the timeout is only accurate to the nearest
tenth of a second.
+Also, the maximum value of
+.Fa delay
+is 25500 milliseconds.
The
.Fn wtimeout
function does the same as
diff -ur /usr/src/lib/libcurses/getch.c ./getch.c
--- /usr/src/lib/libcurses/getch.c 2006-03-19 08:21:32.000000000 +0000
+++ ./getch.c 2006-07-24 21:38:34.000000000 +0100
@@ -594,6 +594,9 @@
k = 0; /* XXX gcc -Wuninitialized */
+#ifdef DEBUG
+ __CTRACE("inkey (%d, %d)\n", to, delay);
+#endif
for (;;) { /* loop until we get a complete key sequence */
reread:
if (state == INKEY_NORM) {
@@ -890,6 +893,10 @@
switch (win->delay)
{
case -1:
+ if (__delay() == ERR) {
+ __restore_termios();
+ return ERR;
+ }
break;
case 0:
if (__nodelay() == ERR) {
diff -ur /usr/src/lib/libcurses/timeout.c ./timeout.c
--- /usr/src/lib/libcurses/timeout.c 2000-04-24 15:09:44.000000000 +0100
+++ ./timeout.c 2006-07-24 21:58:36.000000000 +0100
@@ -71,7 +71,13 @@
else if (!delay)
win->delay = delay;
else {
- /* timeout granularity is ms but VTIME is 0.1s */
- win->delay = delay / 100;
+ /*
+ * 1. VTIME is a char
+ * 2. timeout granularity is ms but VTIME is 0.1s
+ */
+ if (delay > 25500)
+ win->delay = 255;
+ else
+ win->delay = delay / 100;
}
}
diff -ur /usr/src/lib/libcurses/tty.c ./tty.c
--- /usr/src/lib/libcurses/tty.c 2004-01-20 08:30:55.000000000 +0000
+++ ./tty.c 2006-07-24 21:35:02.000000000 +0100
@@ -286,6 +286,9 @@
int
__delay(void)
{
+#ifdef DEBUG
+ __CTRACE("__delay()\n");
+#endif
/* Check if we need to restart ... */
if (_cursesi_screen->endwin)
__restartwin();
@@ -306,6 +309,9 @@
int
__nodelay(void)
{
+#ifdef DEBUG
+ __CTRACE("__nodelay()\n");
+#endif
/* Check if we need to restart ... */
if (_cursesi_screen->endwin)
__restartwin();
@@ -356,6 +362,9 @@
int
__timeout(int delay)
{
+#ifdef DEBUG
+ __CTRACE("__timeout()\n");
+#endif
/* Check if we need to restart ... */
if (_cursesi_screen->endwin)
__restartwin();
@@ -379,6 +388,9 @@
int
__notimeout(void)
{
+#ifdef DEBUG
+ __CTRACE("__notimeout()\n");
+#endif
/* Check if we need to restart ... */
if (_cursesi_screen->endwin)
__restartwin();
- - 8< - - - - - - - - - - - - - Cut here - - - - - - - - - - - - - >8 - -
--
My other computer also runs NetBSD / Sailing at Newbiggin
http://www.netbsd.org/ / http://www.newbigginsailingclub.org/