[Rd] help with gotoExitingHandler(R_NilValue, call, entry); . Implementation of error handling internally
Romain François
romain at r-enthusiasts.com
Thu Feb 27 08:13:23 CET 2014
Of course one problem is that R hides things that I need for this, such as R_HandlerStack and R_ReturnedValue.
I understand they have to be hidden, in which case can we have an exposed mechanism similar to what R_ToplevelExec does, but with the added functionality of giving access to the condition where R_ToplevelExec would return TRUE.
Would someone be willing to review a patch to R with this added functionality. Please.
In any case, I still would like some comments about my initial question about R_NilValue use in gotoExitingHandler(R_NilValue, call, entry);
Romain
Le 26 févr. 2014 à 09:41, Romain François <romain at r-enthusiasts.com> a écrit :
> Hello,
>
> I’m trying to leverage R_ToplevelExec to implement C level try/catch.
>
> The way it is implemented allows for running a function in a top level context. This context gets an empty handler stack, so either the function runs correctly or it jumps. When it jumps, it does not find a handler, so it jumps to the top level context.
>
> R does not allow me to call begin context and end context directly, so instead what I do is call R_ToplevelExec, grab the global context inside the function, install my own handler that I don’t set to be a calling one, pretend this context is a CTXT_FUNCTION.
>
> Eventually I get to jump fun, so that I can later on grab the condition from R_ReturnedValue.
>
> This works well in the « not simple error » case, i.e. if I call stop( simpleError(...) ), but with simple errors, i.e. calls to Rf_error internally or bare calls to stop( "vvzvz" ) I can’t access the error.
>
> And this boils down to this call:
>
> gotoExitingHandler(R_NilValue, call, entry);
>
> inside vsignalError :
>
> static void vsignalError(SEXP call, const char *format, va_list ap)
> {
> char localbuf[BUFSIZE];
> SEXP list, oldstack;
>
> oldstack = R_HandlerStack;
> Rvsnprintf(localbuf, BUFSIZE - 1, format, ap);
> while ((list = findSimpleErrorHandler()) != R_NilValue) {
> char *buf = errbuf;
> SEXP entry = CAR(list);
> R_HandlerStack = CDR(list);
> strncpy(buf, localbuf, BUFSIZE - 1);
> /* Rvsnprintf(buf, BUFSIZE - 1, format, ap);*/
> buf[BUFSIZE - 1] = 0;
> if (IS_CALLING_ENTRY(entry)) {
> if (ENTRY_HANDLER(entry) == R_RestartToken)
> return; /* go to default error handling; do not reset stack */
> else {
> SEXP hooksym, hcall, qcall;
> /* protect oldstack here, not outside loop, so handler
> stack gets unwound in case error is protect stack
> overflow */
> PROTECT(oldstack);
> hooksym = install(".handleSimpleError");
> PROTECT(qcall = LCONS(R_QuoteSymbol,
> LCONS(call, R_NilValue)));
> PROTECT(hcall = LCONS(qcall, R_NilValue));
> hcall = LCONS(mkString(buf), hcall);
> hcall = LCONS(ENTRY_HANDLER(entry), hcall);
> PROTECT(hcall = LCONS(hooksym, hcall));
> eval(hcall, R_GlobalEnv);
> UNPROTECT(4);
> }
> }
> else gotoExitingHandler(R_NilValue, call, entry); // <<< HERE
> }
> R_HandlerStack = oldstack;
> }
>
> Would it be possible to construct a simple condition instead of passing down R_NilValue so that I can grab this error and deal with it.
>
> The alternative is to set the handler to be a calling one, but I’d like to avoid that as much as possible as this means going back to the R side of things just to get access to the condition.
>
> My code is here: https://gist.github.com/romainfrancois/9225811
>
> I have only tested this on OSX with R-devel. The code only uses R internal api (not Rcpp*).
>
> So down to what I’d like you to consider please if you are still reading here. Can we feed gotoExitingHandler with something more interesting than NULL. please.
>
>
>
> The end game is to add one layer of abstraction, e.g. pass to R_ToplevelExec a function that first deals with contexts, then calls an actual function. Combining this with lambda functions in C++ will make quite a nice and elegant way to handle error handling at the C++ level.
>
> I can provide the code that would create the simpleError, this is just making a simple VECSXP with names and classes, no big trouble here.
>
> Romain
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list