[Rd] WISHLIST: Be able to timeout readline()/stdin via setTimeLimit in all consoles
Henrik Bengtsson
hb at biostat.ucsf.edu
Fri Jan 13 04:17:18 CET 2012
Hi.
WISHLIST:
Regardless on console, I'd like to be able to timeout a call to
readline()/file("stdin", blocking=TRUE) via setTimeLimit.
OBSERVATION:
On Windows Rterm as well as plain R on Linux, setTimeLimit() does not
momentarily interrupt from stdin, but only after hitting RETURN. A
few examples:
timeout00 <- function() {
setTimeLimit(elapsed=5);
Sys.sleep(10);
}
timeout01 <- function() {
setTimeLimit(elapsed=5);
readline();
}
timeout02 <- function() {
setTimeLimit(elapsed=5);
con <- file("stdin", blocking=TRUE);
on.exit(close(con));
readChar(con, nchars=1);
}
timeout03 <- function() {
setTimeLimit(elapsed=5);
con <- socketConnection(port=6011, blocking=TRUE);
on.exit(close(con));
readChar(con, nchars=1);
}
# Times out after 5 second
> timeout00()
Error in Sys.sleep(10) : reached elapsed time limit
# Times out only after pressing ENTER
> timeout01()
foo
[1] "foo"
Error: reached elapsed time limit
# Times out only after pressing ENTER
> timeout02()
bar
[1] "b"
Error: reached elapsed time limit
# Times out after 5 second
> timeout03()
Error in socketConnection(port = 6011, blocking = TRUE)
reached elapsed time limit
Note also, that it is possible to interrupted timeout01() and
timeout02() via Ctrl+C as well as by sending SIGINT to the R process
(at least on a Linux system).
Doing the same in Rgui, the timeout will indeed timeout:
# Times out after 5 second
> timeout01()
Error in readline() : reached elapsed time limit
# Times out after 5 second (but somehow returns immediately)
> timeout02()
character(0)
Error: reached elapsed time limit
DOCUMENTATION:
The help("setTimeLimit", package="base") documentation says:
"Time limits are checked whenever a user interrupt could occur. This
will happen frequently in R code and during Sys.sleep, but only at
points in compiled C and Fortran code identified by the code author."
Maybe one could clarify/examplify(?) by adding: "Depending on the type
of console, timeouts when reading from stdio (e.g. via readline()) may
not be effective until a line is completed (i.e. ENTER is pressed).
HOW UPDATING SOURCE CODE TO SUPPORT INTERRUPTS?
I'm not sure where this "behavior" is originating from, and whether it
is possible to obtain a cross-platform solution or not. I located the
following native do_readln() function in src/main/scan.c that is
called by readline():
SEXP attribute_hidden do_readln(SEXP call, SEXP op, SEXP args, SEXP rho)
{
...
while ((c = ConsoleGetchar())!= '\n' && c != R_EOF) {
if (bufp >= &buffer[MAXELTSIZE - 2]) continue;
*bufp++ = c;
}
...
}
with ConsoleGetchar():
/* used by readline() and menu() */
static int ConsoleGetchar(void)
{
if (--ConsoleBufCnt < 0) {
ConsoleBuf[CONSOLE_BUFFER_SIZE] = '\0';
if (R_ReadConsole(ConsolePrompt, ConsoleBuf,
CONSOLE_BUFFER_SIZE, 0) == 0) {
R_ClearerrConsole();
return R_EOF;
}
ConsoleBufp = ConsoleBuf;
ConsoleBufCnt = strlen((char *)ConsoleBuf);
ConsoleBufCnt--;
}
/* at this point we need to use unsigned char or similar */
return (int) *ConsoleBufp++;
}
where in turn R_ReadConsole() appears to be specific to platform and
console, e.g. from src/gnuwin32/system.c:
* R_ReadConsole calls TrueReadConsole which points to:
* case 1: GuiReadConsole
* case 2 and 3: ThreadedReadConsole
* case 4: FileReadConsole
* ThreadedReadConsole wake up our 'reader thread' and wait until
* a new line of input is available. The 'reader thread' uses
* InThreadReadConsole to get it. InThreadReadConsole points to:
* case 2: CharReadConsole
* case 3: FileReadConsole
Here I get a bit lost, but there is:
/*2: from character console with getline (only used as InThreadReadConsole)*/
static int
CharReadConsole(const char *prompt, char *buf, int len, int addtohistory)
{
int res = getline(prompt, buf, len);
if (addtohistory) gl_histadd(buf);
return !res;
}
and, AFAIU, getline() is from the GNU getline library. Is it possible
to timeout getline()? At least it appears to be responding to SIGINT.
/Henrik
More information about the R-devel
mailing list