From chuck at sharpsteen.net  Fri Jan 27 20:53:24 2012
From: chuck at sharpsteen.net (Charlie Sharpsteen)
Date: Fri, 27 Jan 2012 11:53:24 -0800
Subject: [Rd] Ignore user interrupts
In-Reply-To: <alpine.DEB.2.00.1201270815280.2339@luke-inspiron>
References: <1327337214864-4321252.post@n4.nabble.com>
	<1327348807154-4321817.post@n4.nabble.com>
	<1327608987129-4331653.post@n4.nabble.com>
	<alpine.DEB.2.00.1201270815280.2339@luke-inspiron>
Message-ID: <CAMEX5swynaZ5q4Wo5Yr706KA2-9d=bsAdu0TOHtGPWL0SFb+9Q@mail.gmail.com>

On Fri, Jan 27, 2012 at 6:25 AM,  <luke-tierney at uiowa.edu> wrote:
> On Thu, 26 Jan 2012, Sharpie wrote:
>> 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`:

...

>> 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?
>
>
> No.
>
> The interrupt managemant we have now is intended for the C level to
> make sure interrupts can only occur where they are safe for the C
> code, and at this point in sleep they are and so do_syssleep enables
> them.


Thanks for the confirmation Luke---I figured Sys.sleep was somehow
explicitly ignoring the suspended state of interrupts. However, it
seems possible that a situation could arise where R needs to sleep
while waiting for some information needed to finish a critical
operation. I agree that this sounds like poorly written code, but it
would be nice to have a "do not disturb" sign that sets up a context
where all code will ignore SIGINTs generated by the user---even if
that code is just napping for a few seconds.

If someone really wants to halt a critical section of code, they
should need a signal like SIGTERM or SIGKILL that expresses the
severity of such an action.


> There is a need for interrupt management at the R level but getting it
> right is not easy. ?It isn't just a matter of suspending them, but
> suspending and and re-enabling them where they are safe. Some code
> that would potentially hang needs to enable them -- typically these
> are operations that could signal other sorts of errors, like read
> errors, timeouts, etc. and code that needs to ensure cleanup code is
> run would need to catch those as well.


The only thing I am worried about are user-generated interrupts. I
have had a few bug reports that are the result of users just being
unlucky enough to signal an interrupt while a filehash operation was
running. I am pretty confident that these operations either complete
or throw an error, so it is very helpful to delay the processing of
SIGINT for a few microseconds until the filehash ops complete.


> (Interrupts are catchable as "interrupt" conditions by the way).


I tried playing around with `tryCatch` before turning my attention to
BEGIN_SUSPEND_INTERRUPTS and didn't have much success. I could not
find any way to create an interrupt handler that returned control to
the interrupted function call at the point where the interrupt was
signaled. For example, the following catches warnings and ignores
them:

    withCallingHandlers(expr, warning = function(w)
invokeRestart("muffleWarning"))

I am looking for a similar restart handler that traps interrupts and
continues on with the original function call as if nothing happened
(or maybe keeps track of the rate at which interrupts are being
signaled and finally breaks out if the user seems insistent).


-Charlie



[Rd] Ignore user interrupts
Charlie Sharpsteen