From chuck at sharpsteen.net  Thu Jan 26 21:16:27 2012
From: chuck at sharpsteen.net (Sharpie)
Date: Thu, 26 Jan 2012 12:16:27 -0800 (PST)
Subject: [Rd] Ignore user interrupts
In-Reply-To: <1327348807154-4321817.post@n4.nabble.com>
References: <1327337214864-4321252.post@n4.nabble.com>
	<1327348807154-4321817.post@n4.nabble.com>
Message-ID: <1327608987129-4331653.post@n4.nabble.com>


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;
> 
>   BEGIN_SUSPEND_INTERRUPTS{
>     result = eval(expr, envir);
>   }END_SUSPEND_INTERRUPTS;
> 
>   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,
world!")})

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
registered:

    > evalWithoutInterrupts({for(i in 1:10000000){log(i)};message("Hello,
world!")})
    ^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
`R_checkActivity`:

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
sys-std.c:127
#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
sys-std.c:338
#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
eval.c:401
#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
eval.c:515
#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
eval.c:471
#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
`evalWithoutInterrupts`:

(gdb) p R_interrupts_suspended 
$1 = FALSE


Bug?

-Charlie


-----
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.



[Rd] Ignore user interrupts
Sharpie