[Rd] Ignore user interrupts

Sharpie chuck at sharpsteen.net
Thu Jan 26 21:16:27 CET 2012

Sharpie wrote
> evalWithoutInterrupts <- function(expr, envir = parent.frame())
> {
>   .Call(do_evalWithoutInterrupts, expr, envir)
> }
> With a C-level implemention:
> SEXPR do_evalWithoutInterrupts(SEXP expr, SEXP envir)
> {
>   SEXP result;
>     result = eval(expr, envir);
>   return result;
> }

Some more info, and a possible bug:

This approach appears to work if I change `evalWithoutInterrupts` so that it
invokes `substitute` on `expr` before passing to the C code:

    evalWithoutInterrupts <- function(expr, envir = parent.frame())
      .Call(do_evalWithoutInterrupts, substitute(expr), envir)

For example, I can do the following (using OS X, R 2.14.1 in Terminal.app):

    eval({for(i in 1:10000000){log(i)};message("Hello, world!")})
    evalWithoutInterrupts({for(i in 1:10000000){log(i)};message("Hello,

The `eval` call can be interrupted by CTRL-C as normal. However, with the
`evalWithoutInterrupts` call, I can tap on CTRL-C and the loop will still
execute, "Hello, world!" will be printed and then the interrupt will be

    > evalWithoutInterrupts({for(i in 1:10000000){log(i)};message("Hello,
    ^C^C^C^C^CHello, world!


The only odd thing I came across was when I tried to test this function
using `Sys.sleep` instead of a long loop:

    evalWithoutInterrupts(Sys.sleep(3);message("Hello, world!")})

The call can be interrupted immediately by CTRL-C. Some poking in GDB
reveals that the call chain passes from my C function
`evalWithoutInterrupts` to `do_syssleep` an finally to `Rf_onintr` through

Breakpoint 1, Rf_onintr () at errors.c:123
123	    if (R_interrupts_suspended) {
(gdb) bt   
#0  Rf_onintr () at errors.c:123
#1  0x00000001001ced41 in R_SelectEx (n=1, readfds=0x10038cdc0,
writefds=0x0, exceptfds=0x0, timeout=0x7fff5fbf8b60, intr=0) at
#2  0x00000001001cf109 in R_checkActivityEx (usec=3000000, ignore_stdin=1,
intr=0) at sys-std.c:329
#3  0x00000001001cf14b in R_checkActivity (usec=3000000, ignore_stdin=1) at
#4  0x00000001001d0fbb in do_syssleep (call=0x1025bb200, op=0x10086d0d8,
args=0x1033679b8, rho=0x1033679f0) at sys-std.c:1299
#5  0x00000001000c7608 in bcEval (body=0x1025ba878, rho=0x1033679f0,
useCache=TRUE) at eval.c:4445
#6  0x00000001000bcb69 in Rf_eval (e=0x1025ba878, rho=0x1033679f0) at
#7  0x00000001000bddd7 in Rf_applyClosure (call=0x103366e38, op=0x1025ba8e8,
arglist=0x103367a60, rho=0x100877ea8, suppliedenv=0x100877ee0) at eval.c:840
#8  0x00000001000bd22e in Rf_eval (e=0x103366e38, rho=0x100877ea8) at
#9  0x00000001000bf879 in do_begin (call=0x103366ee0, op=0x10084e6e0,
args=0x103366dc8, rho=0x100877ea8) at eval.c:1422
#10 0x00000001000bcf40 in Rf_eval (e=0x103366ee0, rho=0x100877ea8) at
#11 0x0000000102fc736d in evalWithoutInterrupts ()

However, at this point the variable `R_interrupts_suspended` is not set to
`TRUE` as I would expect due to the `BEGIN_SUSPEND_INTERRUPTS` block in

(gdb) p R_interrupts_suspended 
$1 = FALSE



Charlie Sharpsteen
Undergraduate-- Environmental Resources Engineering
Humboldt State University
View this message in context: http://r.789695.n4.nabble.com/Ignore-user-interrupts-tp4321252p4331653.html
Sent from the R devel mailing list archive at Nabble.com.

More information about the R-devel mailing list