[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)
|
||||
===========================
|
||||
|
||||
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
|
||||
[Lua] Arrange that destructors of local C++ objects in the wrapper
|
||||
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));
|
||||
unittest(Foo_get_count(), 2);
|
||||
unittest(Foo_get_freearg_count(), 1);
|
||||
# SWIG exception introduced
|
||||
# SWIG exception introduced (return new object case).
|
||||
result <- tryCatch({
|
||||
trigger_internal_swig_exception("null", b);
|
||||
}, warning = function(w) {
|
||||
|
|
@ -26,3 +26,14 @@ result <- tryCatch({
|
|||
})
|
||||
unittest(Foo_get_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);
|
||||
// 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);
|
||||
|
||||
|
||||
|
|
@ -2123,6 +2130,7 @@ int R::functionWrapper(Node *n) {
|
|||
if (need_cleanup) {
|
||||
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, " return R_NilValue;\n", NIL);
|
||||
Delete(cleanup);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue