[Rcpp-devel] Rcpp::exception + threads = disaster

Joshua N Pritikin jpritikin at pobox.com
Fri Feb 7 14:23:36 CET 2020


On Thu, Feb 06, 2020 at 08:40:02PM -0600, Dirk Eddelbuettel wrote:
> On 6 February 2020 at 20:47, Joshua N Pritikin wrote:
> | The Rcpp::exception constructor does,
> | 
> |   rcpp_set_stack_trace(Shield<SEXP>(stack_trace()))
> | 
> | This can corrupt R if called within an OpenMP block.
> 
> ... here. In general, we can _never_ call back into R for anything,
> exceptions or other things.
> 
> The RcppParallel package documentation is quite good and clear about 
> this; it even has extra data types RMatrix and RVector to stay away 
> from R's memory (which Rcpp is close to for performance and zero 
> copy reasons). The Writing R Extensions manual also as a little, but 
> maybe less clearly.  In short, there is simply "so much going with 
> R" that it stands little chance of every being threadsafe.
> 
> Which means that your OpenMP (or pthreads or TBB or ..) code has to 
> stay away from R.

Yeah, so I replaced Rcpp::stop with,

template <typename... Args>
inline void NORET mxThrow(const char* fmt, Args&&... args) {
    throw std::runtime_error( tfm::format(fmt, std::forward<Args>(args)... ).c_str() );
}

And now things work great. But why does Rcpp::stop need to get the 
stack_trace? R's stack trace isn't going to change until the control 
flow returns back to R. So why can't you just set a flag to indicate 
that "some C++ exception happened" and grab the stack_trace 
immediately before returning control to R?

> | It would be nice if there were some warnings about this (mis)usage OR,
> | better, if Rcpp::exception was thread-safe.
> 
> Maybe some clever folks will come up with a sanitizer variant; otherwise I
> just don't see how.


More information about the Rcpp-devel mailing list