Skip to content

[Rcpp-devel] RInside destructor not working properly?

9 messages · Christian Sigg, Darren Cook, Dirk Eddelbuettel

#
The following program

#include <RInside.h>

void foo() {
   RInside R;
}

void bar() {
   RInside R;
}

int main(int argc, const char * argv[]) {
   foo();
   bar();
   return 0;
}

produces a great number of the following two lines

Error: bad target context--should NEVER happen;
please bug.report() [R_run_onexits]

as output.

Question: Is the RInside destructor not working properly? I would have expected that both in foo() and bar(), an instance of R is created and then destroyed immediately, without producing any kind of output.

Context: I'm developing code that calls the OpenCV library from R, with the help of Rcpp. For rapid development and unit testing, I use RInside to set up the environment before calling my C++ function that calls into the OpenCV library. The above mentioned error appears when the second unit test again calls the RInside constructor to set up its test environment.

This is on OS X 10.7 with Xcode 4.4.1 (Apple LLVM Compiler 4.0) and the latest version of the command line tools. I use R 2.15.1 and RInside 0.2.7.

If I avoid calling RInside() twice in the same program, my code is running smoothly.

Thanks for any assistance,
Christian
#
Christian,
On 27 August 2012 at 13:28, Christian Sigg wrote:
| The following program
| 
| #include <RInside.h>
| 
| void foo() {
|    RInside R;
| }
| 
| void bar() {
|    RInside R;
| }
| 
| int main(int argc, const char * argv[]) {
|    foo();
|    bar();
|    return 0;
| }
| 
| produces a great number of the following two lines
| 
| Error: bad target context--should NEVER happen;
| please bug.report() [R_run_onexits]
| 
| as output.
| 
| Question: Is the RInside destructor not working properly? I would have expected that both in foo() and bar(), an instance of R is created and then destroyed| immediately, without producing any kind of output.

No, wrong setup. R is single-threaded, and you can have only
precisely __ONE__ instance of R in your program. You have two.

Create one in main() and pass references around.

| Context: I'm developing code that calls the OpenCV library from R, with the help of Rcpp. For rapid development and unit testing, I use RInside to set up the environment before calling my C++ function that calls into the OpenCV library. The above mentioned error appears when the second unit test again calls the RInside constructor to set up its test environment.
| 
| This is on OS X 10.7 with Xcode 4.4.1 (Apple LLVM Compiler 4.0) and the latest version of the command line tools. I use R 2.15.1 and RInside 0.2.7.
| 
| If I avoid calling RInside() twice in the same program, my code is running smoothly.

That's the point. Use one, as R can only be called once per process.

There is a bit of a singleton-alike pattern in RInside::initialize() which
should have caught this. I am a bit surprised you got this far. If anybody
has ideas of how to prevent your design error from even passing the compile
stage I'd be all ears.

Dirk

| 
| Thanks for any assistance,
| Christian
| 
| 
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
#
Dear Dirk

Thank you for the reply (and for Rcpp and RInside).
I was not aware that two instances of R are active at the same time. It was my expectation that by instantiating the RInside class as a local variable, at the end of foo() the destructor R.~RInside() would be called and the encapsulated R instance would be terminated, before a new one is instantiated in bar(). 

I did take a cursory glance at the implementation of ~RInside() before asking the question, and the function call

Rf_endEmbeddedR(0);

gave me that (wrong) impression. I don't know the R implementation internals.
Is it possible to terminate the RInside instance instead, and later start a new one? I don't think that it is proper to modify main() with the unit testing framework that I'm using (gtest), as the tests are discovered without explicitly calling them from main().

Regards
Christian
#
That does seem reasonable :-)
I assume there must be a "nothing we can do about" reason why RInside
works the way it does. So I wonder if you can create a global RInside
instance using a global test environment call?

http://code.google.com/p/googletest/wiki/AdvancedGuide#Global_Set-Up_and_Tear-Down

Darren
#
Hi Christian,
On 27 August 2012 at 14:44, Christian Sigg wrote:
| Dear Dirk
| 
| Thank you for the reply (and for Rcpp and RInside).
| 
| > | Question: Is the RInside destructor not working properly? I would have expected that both in foo() and bar(), an instance of R is created and then destroyed| immediately, without producing any kind of output.
| > 
| > No, wrong setup. R is single-threaded, and you can have only
| > precisely __ONE__ instance of R in your program. You have two.
| 
| I was not aware that two instances of R are active at the same time. It was my expectation that by instantiating the RInside class as a local variable, at the end of foo() the destructor R.~RInside() would be called and the encapsulated R instance would be terminated, before a new one is instantiated in bar(). 

You are of course correct in a narrow sense and in that same sense I was
wrong in my email. You called two consecutive instances of RInside, not two
paralle ones. That could have worked ....

... but we are still talking R here and the underlying R API for C embedding
leaves (as I recall) a bunch of globals around.  So no two sessions.

| I did take a cursory glance at the implementation of ~RInside() before asking the question, and the function call
| 
| Rf_endEmbeddedR(0);
| 
| gave me that (wrong) impression. I don't know the R implementation internals.

Right. If you REALLY want this to work, you need to work at that end -- ie in
R's implementation.  RInside would then gladly piggyback on your work. Maybe
all it takes is a big cleanup function. I don't know.  

| > Create one in main() and pass references around.
| 
| 
| Is it possible to terminate the RInside instance instead, and later start a new one? I don't think that it is proper to modify main() with the unit testing framework that I'm using (gtest), as the tests are discovered without explicitly calling them from main().

Do you have one long running instance of main()?  That may be an issue for
you. 

Dirk
#
On 27 August 2012 at 22:26, Darren Cook wrote:
| > I was not aware that two instances of R are active at the same time.
| > It was my expectation that by instantiating the RInside class as a
| > local variable, at the end of foo() the destructor R.~RInside() would
| > be called and the encapsulated R instance would be terminated, before
| > a new one is instantiated in bar().
| 
| That does seem reasonable :-)

Sure. "In theory, theory and practice are the same. In practice they are not."

Fingers are pointing to the R end of things, rather than the RInside wrapping
of it.  If this can be improved, great.

| > I don't think that it is proper to modify main()
| > with the unit testing framework that I'm using (gtest), as the tests
| > are discovered without explicitly calling them from main().
| 
| I assume there must be a "nothing we can do about" reason why RInside
| works the way it does. So I wonder if you can create a global RInside
| instance using a global test environment call?
| 
| http://code.google.com/p/googletest/wiki/AdvancedGuide#Global_Set-Up_and_Tear-Down

One global instance is also what I do in the Qt embedding example.

Dirk
#
To verify, executing

#include <Rembedded.h>
int main(int argc, char **argv) {
    
    Rf_initEmbeddedR(argc, argv);
    Rf_endEmbeddedR(0);
    
    
    Rf_initEmbeddedR(argc, argv);
    Rf_endEmbeddedR(0);
    
    return 0;
}

results in the same series of error messages. 

This issue was already posted to the R-devel mailing list in 2009, but there was no follow up. I will ask again and see if I get a response.

Best regards
Christian
#
On 27 August 2012 at 17:52, Christian Sigg wrote:
| > Fingers are pointing to the R end of things, rather than the RInside wrapping
| > of it.  If this can be improved, great.
| 
| To verify, executing
| 
| #include <Rembedded.h>
| int main(int argc, char **argv) {
|     
|     Rf_initEmbeddedR(argc, argv);
|     Rf_endEmbeddedR(0);
|     
|     
|     Rf_initEmbeddedR(argc, argv);
|     Rf_endEmbeddedR(0);
|     
|     return 0;
| }
| 
| results in the same series of error messages. 
| 
| This issue was already posted to the R-devel mailing list in 2009, but there was no follow up. I will ask again and see if I get a response.

Good work, and good idea.  But as the R Core team has a very different focus
("start R once, get work done") this may once again fall through the cracks.
Now if you debugged it and suggested a fix to them they might take it. Dunno.

Dirk
1 day later
#
Thanks for the hint Darren, using a global test environment is a good work around. 

Creating a fresh RInside instance for each test would have the benefit of isolating the unit tests from each other. I'll see if I get a response from the R developers.

Regards
Christian