[R] Run destructors of local C++ objects on SWIG_fail
Arrange that destructors of local C++ objects in the wrapper function get run on SWIG_fail (which calls Rf_error() which calls longjmp()). We achieve this by putting almost everything in the function in its own block, and end that right before Rf_error() at which point those destructors will get called.
This commit is contained in:
parent
fefb231bd8
commit
5f96d15943
3 changed files with 25 additions and 1 deletions
|
|
@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.1.0 (in progress)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2022-10-14: olly
|
||||||
|
[R] Arrange that destructors of local C++ objects in the wrapper
|
||||||
|
function get run on SWIG_fail (which calls Rf_error() which calls
|
||||||
|
longjmp()).
|
||||||
|
|
||||||
2022-10-14: olly
|
2022-10-14: olly
|
||||||
[Lua] Arrange that destructors of local C++ objects in the wrapper
|
[Lua] Arrange that destructors of local C++ objects in the wrapper
|
||||||
function get run on SWIG_fail (which calls lua_error() which calls
|
function get run on SWIG_fail (which calls lua_error() which calls
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ unittest(Foo_get_count(), 2);
|
||||||
invisible(trigger_internal_swig_exception("no problem", a));
|
invisible(trigger_internal_swig_exception("no problem", a));
|
||||||
unittest(Foo_get_count(), 2);
|
unittest(Foo_get_count(), 2);
|
||||||
unittest(Foo_get_freearg_count(), 1);
|
unittest(Foo_get_freearg_count(), 1);
|
||||||
# SWIG exception introduced
|
# SWIG exception introduced (return new object case).
|
||||||
result <- tryCatch({
|
result <- tryCatch({
|
||||||
trigger_internal_swig_exception("null", b);
|
trigger_internal_swig_exception("null", b);
|
||||||
}, warning = function(w) {
|
}, warning = function(w) {
|
||||||
|
|
@ -26,3 +26,14 @@ result <- tryCatch({
|
||||||
})
|
})
|
||||||
unittest(Foo_get_count(), 2);
|
unittest(Foo_get_count(), 2);
|
||||||
unittest(Foo_get_freearg_count(), 2);
|
unittest(Foo_get_freearg_count(), 2);
|
||||||
|
# SWIG exception introduced (return by value case).
|
||||||
|
result <- tryCatch({
|
||||||
|
trigger_internal_swig_exception("null");
|
||||||
|
}, warning = function(w) {
|
||||||
|
# print(" Hum... We received a warning, but this should be an error");
|
||||||
|
unittest(1,0);
|
||||||
|
}, error = function(e) {
|
||||||
|
# print(" Gotcha!");
|
||||||
|
unittest(1,1);
|
||||||
|
})
|
||||||
|
unittest(Foo_get_count(), 2);
|
||||||
|
|
|
||||||
|
|
@ -1970,6 +1970,13 @@ int R::functionWrapper(Node *n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Printv(f->def, ")\n{\n", NIL);
|
Printv(f->def, ")\n{\n", NIL);
|
||||||
|
// SWIG_fail in R leads to a call to Rf_error() which calls longjmp()
|
||||||
|
// which means the destructors of any live function-local C++ objects won't
|
||||||
|
// get run. To avoid this happening, we wrap almost everything in the
|
||||||
|
// function in a block, and end that right before Rf_error() at which
|
||||||
|
// point those destructors will get called.
|
||||||
|
if (CPlusPlus) Append(f->def, "{\n");
|
||||||
|
|
||||||
Printv(sfun->def, ")\n{\n", NIL);
|
Printv(sfun->def, ")\n{\n", NIL);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2123,6 +2130,7 @@ int R::functionWrapper(Node *n) {
|
||||||
if (need_cleanup) {
|
if (need_cleanup) {
|
||||||
Printv(f->code, cleanup, NIL);
|
Printv(f->code, cleanup, NIL);
|
||||||
}
|
}
|
||||||
|
if (CPlusPlus) Append(f->code, "}\n");
|
||||||
Printv(f->code, " Rf_error(\"%s %s\", SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n", NIL);
|
Printv(f->code, " Rf_error(\"%s %s\", SWIG_ErrorType(SWIG_lasterror_code), SWIG_lasterror_msg);\n", NIL);
|
||||||
Printv(f->code, " return R_NilValue;\n", NIL);
|
Printv(f->code, " return R_NilValue;\n", NIL);
|
||||||
Delete(cleanup);
|
Delete(cleanup);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue