From luke at stat.uiowa.edu  Tue May 20 21:20:26 2008
From: luke at stat.uiowa.edu (Luke Tierney)
Date: Tue, 20 May 2008 14:20:26 -0500 (CDT)
Subject: [Rd] interrupting native code
In-Reply-To: <4BADEEEE-0C2C-496F-B5BC-B8A95C53FADC@epfl.ch>
References: <B2675BBE-97A5-4012-A855-6955F6EE8246@epfl.ch>
	<alpine.LFD.1.10.0805151533180.22788@gannet.stats.ox.ac.uk>
	<80A6B7A3-7979-4A70-8FBF-3EBA753E093E@epfl.ch>
	<alpine.LFD.1.10.0805161142330.27836@gannet.stats.ox.ac.uk>
	<A213708A-3BA2-4109-B24E-F862DCED9BBF@epfl.ch>
	<Pine.LNX.4.64.0805160635510.10050@itasca2.wildberry.org>
	<4BADEEEE-0C2C-496F-B5BC-B8A95C53FADC@epfl.ch>
Message-ID: <Pine.OSX.4.64.0805201418230.1862@luke-tierneys-computer-3.local>

On Tue, 20 May 2008, Kjell Konis wrote:

> I would actually prefer a mechanism that simply returns a flag indicating 
> that an interrupt has been requested. Then I would be able to clean up and 
> return on my own - no longjmp required.

Whether that makes sense depends on why the jump is being taken.  In
most cses I suspect that stopping the jump is OK but there may be
cases where it is not -- this is one of the issues that needs thinking
through.

luke

Also, it would be useful if there was 
> a function similar to R_ProcessEvents that only dealt with keeping the GUI 
> responsive.
>
> Cheers,
> Kjell
>
>
> On 16 mai 08, at 13:54, Luke Tierney wrote:
>
>> I'm not sure you can make this work as some of the things needed
>> either are or should be private to the core implementation and not
>> available to package code.  In any case I would not recommend this
>> approach for two reasons.  First, details of what happens in interrupt
>> checking are subject to change and your code would miss those changes
>> unless you track them carefully.  More importantly, several things
>> here could generate an error that results in a longjmp and leaves your
>> code in an unstable state.
>> 
>> What is needed for this is a mechanism for detecting an interrupt but
>> not doing the longjmp, just returning a flag that a longjmp is needed
>> and enough information to allow it to be made after cleanup code has
>> been run.  This has been on my to do list for a while but getting the
>> semantics right is tricky and so it hasn't happened yet.  Hopefully it
>> will be in 2.8.0.  In the interim you can cobble something together
>> using R_ToplevelExec, interpreting all FALSE return values as user
>> interrupts.
>> 
>> Another option, also under consideration but not available yet, is a C
>> mechanism for registering cleanup operations if a longjmp occurs.  A
>> quick and dirty version of that could be provided fairly easily but a
>> better version, which would be preferable in the long run, requires a
>> rewrite of the code that implements jumps and cleanup/on.exit actions.
>> This may take a bit longer to implement.
>> 
>> Best,
>> 
>> luke
>> 
>> On Fri, 16 May 2008, Kjell Konis wrote:
>> 
>>> You mean something like this (I return 1 instead of calling onintr())? 
>>> Will HAVE_AQUA and Win32 be appropriately defined when building my package 
>>> (I can't see how to check with R CMD config)?
>>> 
>>> int My_CheckUserInterrupt(void)
>>> {
>>> R_CheckStack();
>>> 
>>> #if  ( defined(HAVE_AQUA) )
>>> 
>>> /* R_ProcessEvents() from unix/aqua.c*/
>>> 
>>> if (ptr_R_ProcessEvents)
>>> ptr_R_ProcessEvents();
>>> if (R_interrupts_pending)
>>> return(1);
>>> 
>>> #elseif ( defined(Win32) )
>>> 
>>> /* R_ProcessEvents() from gnuwin32/system.c */
>>> 
>>> while (peekevent()) doevent();
>>> if (UserBreak) {
>>> 	UserBreak = FALSE;
>>> 	return(1);
>>> }
>>> R_CallBackHook();
>>> if(R_tcldo) R_tcldo();
>>> 
>>> #else
>>> 
>>> R_PolledEvents();
>>> if (R_interrupts_pending)
>>> 	return(1);
>>> 
>>> #endif
>>> 
>>> return(0);
>>> }
>>> 
>>> 
>>> 
>>> 
>>> On 16 mai 08, at 12:43, Prof Brian Ripley wrote:
>>> 
>>>> On Fri, 16 May 2008, Kjell Konis wrote:
>>>>> The problem is that my package uses an external pointer to keep track of 
>>>>> a structure created by the lp_solve library. If I use 
>>>>> R_CheckUserInterrupt in the lp_solve abort function it leaves the 
>>>>> structure in a messed-up state after an interrupt occurs. I am not even 
>>>>> able to free the memory allocated in the structure. I need to be able to 
>>>>> tell the lp_solve functions to interrupt themselves if I am going to 
>>>>> support interrupts at all.
>>>>> I took a longer look at errors.c and it seems my solution should work as 
>>>>> long as neither HAVE_AQUA nor Win32 are defined. Under the 
>>>>> circumstances, I think that's the best I can do.
>>>>> Any suggestions for a UI independent way to check for interrupts would 
>>>>> be appreciated.
>>>> Why not use the same code as R_CheckUserInterrupt but instead of calling 
>>>> onintr, call your own interrupt routine?
>>>>> Thanks,
>>>>> Kjell
>>>>> On 15 mai 08, at 16:41, Prof Brian Ripley wrote:
>>>>>> How is R_interrupts_pending going to be set?
>>>>>> It is set in the interrupt handler for SIGINT, but that is not the only 
>>>>>> way to indicate an interrupt, and it is not necessarily available to 
>>>>>> users of GUIs and embedded R.
>>>>>> Without servicing the GUIs all interaction will be dead, including 
>>>>>> sending an interrrupt from menus/buttons/keyboard.  See the comment in 
>>>>>> the code for R_CheckUserInterrupt.
>>>>>> On Thu, 15 May 2008, Kjell Konis wrote:
>>>>>>> Hello,
>>>>>>> I have some native code that I would like to allow users to interrupt. 
>>>>>>> However, I would like to do it more gracefully than with 
>>>>>>> R_CheckUserInterrupt(). The solution I came up with is to call the 
>>>>>>> following abort function periodically - if it returns 1 then I clean 
>>>>>>> up and return.
>>>>>>> int __WINAPI RlpSolveAbortFunction(lprec *lp, void *userhandle)
>>>>>>> {
>>>>>>> if(R_interrupts_pending)
>>>>>>> return(1);
>>>>>>> return(0);
>>>>>>> }
>>>>>>> This seems to work fine on Mac (sans Aqua) and Linux. Is this going to 
>>>>>>> be portable?  Also, is there anything else I need to do?  For instance 
>>>>>>> set R_interrupts_pending to 0 after I respond to it?
>>>>>>> Thanks.
>>>>>>> Kjell
>>>>>>> ______________________________________________
>>>>>>> R-devel at r-project.org mailing list
>>>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>>>> -- 
>>>>>> Brian D. Ripley,                  ripley at stats.ox.ac.uk
>>>>>> Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
>>>>>> University of Oxford,             Tel:  +44 1865 272861 (self)
>>>>>> 1 South Parks Road,                     +44 1865 272866 (PA)
>>>>>> Oxford OX1 3TG, UK                Fax:  +44 1865 272595
>>>>> ______________________________________________
>>>>> R-devel at r-project.org mailing list
>>>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>>> -- 
>>>> Brian D. Ripley,                  ripley at stats.ox.ac.uk
>>>> Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
>>>> University of Oxford,             Tel:  +44 1865 272861 (self)
>>>> 1 South Parks Road,                     +44 1865 272866 (PA)
>>>> Oxford OX1 3TG, UK                Fax:  +44 1865 272595
>>> 
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> 
>> -- 
>> Luke Tierney
>> Chair, Statistics and Actuarial Science
>> Ralph E. Wareham Professor of Mathematical Sciences
>> University of Iowa                  Phone:             319-335-3386
>> Department of Statistics and        Fax:               319-335-3017
>>  Actuarial Science
>> 241 Schaeffer Hall                  email:      luke at stat.uiowa.edu
>> Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
>

-- 
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      luke at stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu



[Rd] interrupting native code
Luke Tierney