[Rd] interrupting native code

Kjell Konis kjell.konis at epfl.ch
Wed May 21 09:28:36 CEST 2008


I have a structure from a library that I am using an external pointer  
to keep track of. The methods in this library (lp_solve) have the  
facility to call a function periodically and I would like to use  
R_ProcessEvents. The problem is that if an interrupt is requested then  
R returns to the command prompt without completing the library method.  
This leaves the structure in a messed-up state so that I can't even  
successfully delete it, potentially leaking a lot of memory. So what I  
am trying to do is find a way to see if an event has occurred (in this  
case an interrupt) so I can respond to it before onintr() gets called.

Kjell


On 20 mai 08, at 19:22, Simon Urbanek wrote:

>
> On May 20, 2008, at 10:58 AM, 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. Also,  
>> it would be useful if there was a function similar to  
>> R_ProcessEvents that only dealt with keeping the GUI responsive.
>>
>
> I don't understand what you mean by the last sentence - that is  
> exactly what R_ProcessEvents is for - or am I missing something?
>
> Cheers,
>
> Simon
>
>
>> 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
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>



More information about the R-devel mailing list