Hi! We?ve recently come across an example where a package (minqa) creates an Rcpp Function object in a static variable. This causes R_ReleaseObject to be called by the destructor at a very late point in time - as part of the system exit function: static Function cf("c"); I?m wondering if that is considered to be ?safe?? Is the R engine supposed to stay in a state where calls to API functions are valid, even after it has shut down? It probably only ever happens with the ReleaseObject function, but even that could cause problems, e.g., with more elaborate refcounting schemes. - Lukas
Calling R_ReleaseObject in a C++ destructor is not reliable - it can be bypassed by a non-local return, such as an error. Generally in R one cannot use C++ destructors reliably for anything that the R runtime wouldn't do on its own in case of a non-local return. A destructor that calls just UNPROTECT, in a way that balances out the protection stack (e.g. Rcpp Shield), is safe because R runtime balances the protection stack on non-local return. Destructors used in code that will never call into any R API (such as in a third party library) are safe, because the R runtime could not do non-local return. All other destructors are a problem. UNPROTECT will work even during R shutdown. In some cases cleanup code that would be put in C++ destructors, if they were safe with R, can instead be put into R finalizers. Tomas On 09/21/2017 04:41 PM, Lukas Stadler wrote:> Hi! > > We?ve recently come across an example where a package (minqa) creates an Rcpp Function object in a static variable. > This causes R_ReleaseObject to be called by the destructor at a very late point in time - as part of the system exit function: > > static Function cf("c"); > > I?m wondering if that is considered to be ?safe?? > Is the R engine supposed to stay in a state where calls to API functions are valid, even after it has shut down? > It probably only ever happens with the ReleaseObject function, but even that could cause problems, e.g., with more elaborate refcounting schemes. > > - Lukas > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel
If this is not considered to be safe, then I guess my message can be seen as a heads-up: If R_ReleaseObject ever does something that is not safe after the R engine has shut down, you will start to see crashes from packages like ?minqa?. In FastR, we ended up adding a global flag that disables parts of the native API because of this. - Lukas> On 21 Sep 2017, at 17:53, Tomas Kalibera <tomas.kalibera at gmail.com> wrote: > > > Calling R_ReleaseObject in a C++ destructor is not reliable - it can be bypassed by a non-local return, such as an error. Generally in R one cannot use C++ destructors reliably for anything that the R runtime wouldn't do on its own in case of a non-local return. > > A destructor that calls just UNPROTECT, in a way that balances out the protection stack (e.g. Rcpp Shield), is safe because R runtime balances the protection stack on non-local return. Destructors used in code that will never call into any R API (such as in a third party library) are safe, because the R runtime could not do non-local return. All other destructors are a problem. > > UNPROTECT will work even during R shutdown. > > In some cases cleanup code that would be put in C++ destructors, if they were safe with R, can instead be put into R finalizers. > > Tomas > > > > On 09/21/2017 04:41 PM, Lukas Stadler wrote: >> Hi! >> >> We?ve recently come across an example where a package (minqa) creates an Rcpp Function object in a static variable. >> This causes R_ReleaseObject to be called by the destructor at a very late point in time - as part of the system exit function: >> >> static Function cf("c"); >> >> I?m wondering if that is considered to be ?safe?? >> Is the R engine supposed to stay in a state where calls to API functions are valid, even after it has shut down? >> It probably only ever happens with the ReleaseObject function, but even that could cause problems, e.g., with more elaborate refcounting schemes. >> >> - Lukas >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwIDaQ&c=RoP1YumCXCgaWHvlZYR8PQcxBKCX5YTpkKY057SbK10&r=6DzVcyWX6yyD2r4eAolUQDWVUN_xc9UW6UdTto2_bao&m=YltTQ4tUmVFt23AnHzDGTPVCXmlUiOq1ayKJzhavePU&s=qibOCsqERij4Ymssp_hIfB78JDOA8v0jSYJ7ZTnCNO4&e= > >
Possibly Parallel Threads
- calling R API functions after engine shutdown
- Repost: (apologies for HTML post) A question about multiple(?) out of order ReleaseObject
- Many apologies: last post: A question about multiple(?) out of order ReleaseObject
- A question about multiple(?) out of order ReleaseObject
- R_PreserveObject, R_ReleaseObject : reference counting needed ?