[Rcpp-devel] RCPP_USE_UNWIND_PROTECT by default

Kevin Ushey kevinushey at gmail.com
Mon Feb 7 03:10:54 CET 2022


Thanks, I think I understand the issue better now. Ultimately, it comes
down to the fact that UnwindProtect doesn't really allow handling of R
conditions in the "regular" way as e.g. tryCatch() does; instead, it gives
us just enough to properly unwind the C++ stack when an R error occurs. If
I can summarize:

1. Client packages can catch the Rcpp LongjumpException and handle it
themselves if they need to, but it's not obvious how to do this correctly.
2. R error messages are printed by R when the error is emitted.
3. It's not clear to the LongJumpException handler what R error triggered
the longjmp exception.

In particular, for (1), Rcpp is normally responsible for unprotecting its
unwind token, and then continuing the unwind:

https://github.com/RcppCore/Rcpp/blob/1c8a1946db56e4d8041593906eddcb0da8ba07a0/inst/include/Rcpp/exceptions.h#L148-L157

If we want to make it safe for client packages to catch these exceptions,
we'd need to provide a helper for cleaning up Rcpp's unwind state, or make
that happen automatically. (Maybe the token's protection status could be
managed as part of the exception's lifetime? Not sure.) However, the fact
that the LongjumpException needs special handling implies that it probably
shouldn't inherit from std::exception.

For (2), I don't see a clean way of handling this beyond setting the
'show.error.messages' option to false. Unfortunately, because UnwindProtect
is not a "real" R condition handler, it gets processed only after the
"regular" R error machinery runs (which includes printing the error before
actually jumping).

I'm similarly not aware of any solution for (3).

In other words, my understanding is that if you're a client of Rcpp and you
want to be able to catch and handle R errors at the C++ level,
UnwindProtect() isn't the right tool -- you'll want a proper tryCatch()
handler.

It does also imply (as had been shown) that switching to unwind-protect
would be a behavior change in Rcpp, which may not be ideal.

Thanks,
Kevin




On Sun, Feb 6, 2022 at 9:39 AM Jeroen Ooms <jeroenooms at gmail.com> wrote:

> On Sun, Feb 6, 2022 at 6:25 PM Kevin Ushey <kevinushey at gmail.com> wrote:
> >
> > If I tweak your example package code so that all exceptions are caught
> via a catch (...) {} block, I can see something like:
> >
> > > uptest::uptest()
> > Error in (function ()  : Ouch from R
> > Caught some other exception.
> >
> > The fact that we're still printing the R error message seems
> undesirable, but it looks like the exception can be caught -- just not via
> std::exception.
>
> Yes that is also what IƱaki and me alluded to above. But I think this
> way, what we are catching is not the R error itself (which seems lost
> after it was printed), but rather a token that tells the application
> we should let Rcpp unwind all the way back to the R console. Which is
> what happens if we don't catch it, then it makes sense. But if we _do_
> want to handle the situation in C++, this doesn't give us much to work
> with.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20220206/dc08ac08/attachment.html>


More information about the Rcpp-devel mailing list