diff --git a/CHANGES.current b/CHANGES.current index 123c51f12..e08aa5cb6 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -12,6 +12,11 @@ Version 4.0.0 (in progress) Similar to the earlier PEP 366 conforming fix for non-builtin. +2018-11-29: adr26 + [Python] #1360 Leak of SWIG var link object + + Fix reference counting on _SWIG_globals to allow var link to be freed on module unload. + 2018-11-28: wsfulton [Python] When using -builtin, the two step C-extension module import is now one step and the wrapped API is only available once and not in an underlying diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 621d6f9ed..d8f3bf444 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -326,7 +326,8 @@ SWIGEXPORT void #endif SWIG_init(void) { - PyObject *m, *d, *md; + PyObject *m, *d, *md, *globals; + #if PY_VERSION_HEX >= 0x03000000 static struct PyModuleDef SWIG_module = { PyModuleDef_HEAD_INIT, @@ -379,6 +380,8 @@ SWIG_init(void) { assert(metatype); #endif + (void)globals; + /* Create singletons now to avoid potential deadlocks with multi-threaded usage after module initialization */ SWIG_This(); SWIG_Python_TypeCache(); diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 396a5d22e..66d34992a 100755 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -3319,7 +3319,17 @@ public: Python dictionary. */ if (!have_globals) { - Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", SWIG_globals());\n", global_name); + Printf(f_init, "\t globals = SWIG_globals();\n"); + Printf(f_init, "\t if (!globals) {\n"); + Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Failure to create SWIG globals.\");\n"); + Printf(f_init, "#if PY_VERSION_HEX >= 0x03000000\n"); + Printf(f_init, "\t return NULL;\n"); + Printf(f_init, "#else\n"); + Printf(f_init, "\t return;\n"); + Printf(f_init, "#endif\n"); + Printf(f_init, "\t }\n"); + Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", globals);\n", global_name); + Printf(f_init, "\t Py_DECREF(globals);\n"); if (builtin) Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; @@ -3407,9 +3417,9 @@ public: Wrapper_print(getf, f_wrappers); /* Now add this to the variable linking mechanism */ - Printf(f_init, "\t SWIG_addvarlink(SWIG_globals(), \"%s\", %s, %s);\n", iname, vargetname, varsetname); + Printf(f_init, "\t SWIG_addvarlink(globals, \"%s\", %s, %s);\n", iname, vargetname, varsetname); if (builtin && shadow && !assignable && !in_class) { - Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", PyObject_GetAttrString(SWIG_globals(), \"%s\"));\n", iname, iname); + Printf(f_init, "\t PyDict_SetItemString(md, \"%s\", PyObject_GetAttrString(globals, \"%s\"));\n", iname, iname); Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname); } Delete(vargetname);