[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