From: tkorvola Date: Tue, 7 Feb 2017 17:40:00 +0000 (+0200) Subject: Plug more reference leaks. X-Git-Tag: v1.31.0^0 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=60a974076fd7fd49df930b18a212a117ea7d032c;p=simantics%2Fpython.git Plug more reference leaks. I hope I am getting it right. The Python C API is a bit messy regarding reference behaviour. Change-Id: I0e78b4f8e46eb387caf0d751f6bffac5f1b10c18 --- diff --git a/org.simantics.pythonlink.win32.x86_64/jnipython.dll b/org.simantics.pythonlink.win32.x86_64/jnipython.dll index c2f62cb..7cc11fd 100644 Binary files a/org.simantics.pythonlink.win32.x86_64/jnipython.dll and b/org.simantics.pythonlink.win32.x86_64/jnipython.dll differ diff --git a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c index caed56d..762df28 100644 --- a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c +++ b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c @@ -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);