]> gerrit.simantics Code Review - simantics/python.git/commitdiff
Plug more reference leaks. 32/332/1 release/1.31.0 release/1.32.0 release/1.32.0.1 release/1.32.0.2 release/1.32.1 release/1.33.0 release/1.34.0 release/1.34.1 release/1.34.2 v1.31.0
authortkorvola <Timo.Korvola@vtt.fi>
Tue, 7 Feb 2017 17:40:00 +0000 (19:40 +0200)
committertkorvola <Timo.Korvola@vtt.fi>
Wed, 8 Feb 2017 11:29:39 +0000 (13:29 +0200)
I hope I am getting it right.  The Python C API is a bit messy
regarding reference behaviour.

Change-Id: I0e78b4f8e46eb387caf0d751f6bffac5f1b10c18

org.simantics.pythonlink.win32.x86_64/jnipython.dll
org.simantics.pythonlink.win32.x86_64/src/sclpy.c

index c2f62cb7f5de3bbfa0d808fa900bb308711c0fab..7cc11fd3f764998be28d7d5c889260ff1499bb2d 100644 (file)
Binary files a/org.simantics.pythonlink.win32.x86_64/jnipython.dll and b/org.simantics.pythonlink.win32.x86_64/jnipython.dll differ
index caed56dc8c8ab30e3cc9c0d2437969eca7470571..762df28e988aaee4b451efe8dfe5f788ccbf304e 100644 (file)
@@ -32,6 +32,7 @@ jint throwIllegalArgumentException( JNIEnv *env, const char *message ) {
        return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );
 }
 
+// Returns a borrowed reference.
 PyObject* getModule(jlong contextID) {
        return PyState_FindModule((PyModuleDef*) contextID);
 //     return PyImport_AddModule("__main__");
@@ -105,19 +106,27 @@ static PyMethodDef sclWriterMethods[] = {
     {NULL, NULL, 0, NULL}
 };
 
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_initializePython(JNIEnv *env, jobject thisObj, jobject writer) {
+JNIEXPORT void JNICALL
+Java_org_simantics_pythonlink_PythonContext_initializePython(
+        JNIEnv *env, jobject thisObj, jobject writer) {
     Py_Initialize();
 
     {
-       static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "sclwriter", NULL, -1, sclWriterMethods, };
-               PyObject *m = PyModule_Create(&moduledef);
+       static struct PyModuleDef moduledef = {
+           PyModuleDef_HEAD_INIT, "sclwriter", NULL, -1, sclWriterMethods
+       };
+       PyObject *m = PyModule_Create(&moduledef);
 
        sclWriter = (*env)->NewGlobalRef(env, writer);
 
-       if (m == NULL) throwException(env, PYTHON_EXCEPTION, "Failed to create SCL writer module");
-
-               PySys_SetObject("stdout", m);
-               PySys_SetObject("stderr", m);
+       if (m == NULL) {
+           throwException(env, PYTHON_EXCEPTION,
+                          "Failed to create SCL writer module");
+       } else {
+           PySys_SetObject("stdout", m);
+           PySys_SetObject("stderr", m);
+           Py_DECREF(m);
+       }
     }
 
        hasNumpy = _import_array();
@@ -145,12 +154,11 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContex
                modDef->m_size = -1;
 
                module = PyModule_Create(modDef);
-               Py_INCREF(module);
                PyState_AddModule(module, modDef);
-
                {
                        PyObject *builtin = PyImport_AddModule("builtins");
                        PyObject *dict = PyModule_GetDict(module);
+                       Py_DECREF(module);
                        PyDict_SetItemString(dict, "__builtin__", builtin);
                        PyDict_SetItemString(dict, "__builtins__", builtin);
 
@@ -160,12 +168,11 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_createContex
        }
 }
 
-JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(JNIEnv *env, jobject thisObj, jlong contextID) {
+JNIEXPORT void JNICALL
+Java_org_simantics_pythonlink_PythonContext_deleteContextImpl(
+               JNIEnv *env, jobject thisObj, jlong contextID) {
        PyModuleDef *modDef = (PyModuleDef*)contextID;
-       PyObject *module;
        PyEval_RestoreThread(main_ts);
-       module = PyState_FindModule(modDef);
-       Py_XDECREF(module);
        PyState_RemoveModule(modDef);
        free((char*)modDef->m_name);
        free(modDef);
@@ -204,6 +211,7 @@ PyObject *getPythonStringList(JNIEnv *env, jobjectArray value) {
                        PyList_SetItem(result, i, getPythonString(env, (jstring)item));
                }
                else {
+                       Py_INCREF(Py_None);
                        PyList_SetItem(result, i, Py_None);
                }
        }
@@ -416,8 +424,12 @@ PyObject *getPythonRecordObject(JNIEnv *env, jobject object, jobject binding) {
                jobject componentObject = (*env)->CallObjectMethod(env, binding, getComponent, object, i);
                jobject componentBinding = (*env)->CallObjectMethod(env, binding, getComponentBinding, i);
 
-               PyObject *item = getPythonObject(env, componentObject, componentBinding);
-               PyDict_SetItem(result, getPythonString(env, fieldName), item);
+               PyObject
+                       *key = getPythonString(env, fieldName),
+                       *item = getPythonObject(env, componentObject, componentBinding);
+               PyDict_SetItem(result, key, item);
+               Py_DECREF(key);
+               Py_DECREF(item);
        }
 
        return result;
@@ -440,8 +452,10 @@ PyObject *getPythonArrayObject(JNIEnv *env, jobject object, jobject binding) {
                jobject item = (*env)->CallObjectMethod(env, binding, getMethod, object, i);
                if (item != NULL)
                        PyList_SetItem(result, i, getPythonObject(env, item, componentBinding));
-               else
+               else {
+                       Py_INCREF(Py_None);
                        PyList_SetItem(result, i, Py_None);
+               }
        }
 
        return result;
@@ -470,7 +484,12 @@ PyObject *getPythonMapObject(JNIEnv *env, jobject object, jobject binding) {
        for (i = 0; i < size; i++) {
                jobject key = (*env)->GetObjectArrayElement(env, keys, i);
                jobject item = (*env)->GetObjectArrayElement(env, values, i);
-               PyDict_SetItem(result, getPythonObject(env, key, keyBinding), getPythonObject(env, item, valueBinding));
+               PyObject
+                       *pkey = getPythonObject(env, key, keyBinding),
+                       *pitem = getPythonObject(env, item, valueBinding);
+               PyDict_SetItem(result, pkey, pitem);
+               Py_DECREF(pkey);
+               Py_DECREF(pitem);
        }
 
        (*env)->DeleteLocalRef(env, keys);
@@ -601,6 +620,7 @@ PyObject *getPythonObject(JNIEnv *env, jobject value, jobject binding) {
        }
 }
 
+// Steals refs to name & value.
 void setPythonVariable(PyObject *module, PyObject *name, PyObject *value) {
        if (name && value) {
                PyDict_SetItem(PyModule_GetDict(module), name, value);
@@ -1013,8 +1033,8 @@ Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(
 
                {
                        PyObject *result = PyRun_String(utfchars, Py_file_input, globals, globals);
-
                        PyObject *exceptionType = PyErr_Occurred();
+
                        if (exceptionType != NULL) {
                                PyObject *exception, *traceback, *message;
                                PyErr_Fetch(&exceptionType, &exception, &traceback);
@@ -1055,7 +1075,7 @@ Java_org_simantics_pythonlink_PythonContext_executePythonStatementImpl(
 // Returns a borrowed reference.
 static PyObject *getPythonValue(
                JNIEnv *env, jlong contextID, jstring variableName) {
-       PyObject *module = getModule(contextID);
+    PyObject *module = getModule(contextID);
     PyObject *pythonName = getPythonString(env, variableName);
     PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);