[R] Wait for keystroke or timeout

William Dunlap wdunlap at tibco.com
Fri May 28 18:29:02 CEST 2010

> -----Original Message-----
> From: r-help-bounces at r-project.org 
> [mailto:r-help-bounces at r-project.org] On Behalf Of Prof. John C Nash
> Sent: Friday, May 28, 2010 7:46 AM
> Cc: r-help at r-project.org
> Subject: Re: [R] Wait for keystroke or timeout
> Matt's suggestion works in Linux (I use Ubuntu and Debian 
> variants), but I haven't yet
> been able to get it to work in Windows.

Another sort of solution would be a timeout()
function.   timeout(expr, seconds=5), where expr is an
expression to be evaluated, would return the value of
expr if if could be evaluated in the given number of
seconds.  If the evaluation of expr were not done in
a given number of seconds timeout() would do something
else: throw an error or return something of class "timedOut"
or ???.

I wrote one for S+ a long time ago when our QA department
wanted a way to check that an infinite-loop bug was gone.
Here is an R verion of that code which works only on Unix,
as it relies on have a shell available and on being able
to use Unix signals.   It throws an error if there is a
timeout.  You can catch the error with try or tryCatch
or withCallingHandlers.

I don't know if there is a similar thing in R now.  There
is a setTimeLimit function but I haven't played with enough
to know if it can do this.

function(expr, seconds = 60)
        # Set up a background process that will send a signal
        # to the current R process after 'seconds' seconds.
        # Evaluate expr with an interrupt handler installed
        # to catch the interrupt.
        # If expr finishes before that time it will kill the killer.
        killer.pid <- system(intern = TRUE, paste(" (sleep", seconds,
                " ; kill -INT", Sys.getpid(),
                ")>/dev/null&\n echo $!"))
        on.exit(system(paste("kill", killer.pid, "> /dev/null 2>&1")))
        withCallingHandlers(expr, interrupt=function(...)stop("Timed
out", call.=FALSE))

Try it on Linux with
  > z <- try(silent=TRUE, timeout(readline(prompt="Hit me: "),
  Hit me: 34
  > z
  [1] "34"
  > z <- try(silent=TRUE, timeout(readline(prompt="Hit me: "),
  Hit me: > z
  [1] "Error : Timed out\n"
  [1] "try-error"

I don't know if this sort of user-interface stuff belongs
in R itself, but killing jobs that go on for too long can
be useful.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com 

> In a DOS terminal, I 
> can run Cygwin's blas.exe via
>    blas -c "read -t 1 -n 1"
> and get the right functioning, but when embedded in R in 
> various ways, I get several error
> messages that imply R is not finding or interpreting the 
> command correctly.
> As the details are arcane, please contact me off-line, and 
> I'll report back to the list
> when we have a solution.
> However, if someone could try Matt's suggestion on a Mac and 
> let me know outcome, that
> would be helpful. Since .Platform allows me to determine OS 
> type, I should be able to work
> out a more or less platform-independent function.
> JN
> biostatmatt wrote:
> > On Thu, 2010-05-27 at 19:08 -0400, Prof. John C Nash wrote:
> >> I would like to have a function that would wait either 
> until a specified timeout (in
> >> seconds preferably) or until a key is pressed. 
> > .... If you are using Linux
> > you can use try this
> > 
> >> system("read -t 1 -n 1")
> > 
> > where -n indicates the number of characters to read and -t 
> specifies the
> > timeout in seconds.
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide 
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

More information about the R-help mailing list