Changeset: 4f4eafa3b4fd for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4f4eafa3b4fd
Modified Files:
        monetdb5/extras/pyapi/Tests/random_file.py
        monetdb5/extras/pyapi/pyapi.c
        monetdb5/extras/pyapi/pyapi.mal
Branch: pyapi
Log Message:

Fixed a few memory leaks.


diffs (184 lines):

diff --git a/monetdb5/extras/pyapi/Tests/random_file.py 
b/monetdb5/extras/pyapi/Tests/random_file.py
--- a/monetdb5/extras/pyapi/Tests/random_file.py
+++ b/monetdb5/extras/pyapi/Tests/random_file.py
@@ -1,9 +1,9 @@
-for j in range(1,15):
+for j in range(1,2):
     f = open('workfile' + str(j) + '.sql', 'w')
     import random
     random.seed()
     f.write("START TRANSACTION;\n")
-    for i in range(1, 1000000):
+    for i in range(1, 50000):
         f.write("INSERT INTO rval VALUES ")
         x = random.randint(0,100)
         y = random.randint(0,100)
diff --git a/monetdb5/extras/pyapi/pyapi.c b/monetdb5/extras/pyapi/pyapi.c
--- a/monetdb5/extras/pyapi/pyapi.c
+++ b/monetdb5/extras/pyapi/pyapi.c
@@ -188,8 +188,11 @@ static int pyapiInitialized = FALSE;
                                                                       \
             }                                                         \
         } bat->T->nonil = 1 - bat->T->nil;                            \
-        BATsetcount(bat, ret->count); \
-        BATsettrivprop(bat); }
+        BATsetcount(bat, ret->count);                                 \
+        BATsettrivprop(bat);                                          \
+        Py_DECREF(ret->numpy_array);                                  \
+        if (ret->numpy_mask != NULL) Py_DECREF(ret->numpy_mask);       \
+    }
 
 #define NP_CREATE_BAT_COL(bat, mtpe, nptpe) {                               \
         bool *mask = NULL; \
@@ -218,7 +221,10 @@ static int pyapiInitialized = FALSE;
             }                                                         \
         } bat->T->nonil = 1 - bat->T->nil;                            \
         BATsetcount(bat, ret->count); \
-        BATsettrivprop(bat); }
+        BATsettrivprop(bat); \
+        Py_DECREF(ret->numpy_array);                                  \
+        if (ret->numpy_mask != NULL) Py_DECREF(ret->numpy_mask);       \
+    }
 
 str PyAPIeval(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit grouped, bit 
mapped);
 
@@ -289,7 +295,7 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
     PyObject *pArgs, *pResult; // this is going to be the parameter tuple
     BUN p = 0, q = 0;
     BATiter li;
-    PyGILState_STATE gstate;
+    PyGILState_STATE gstate = -1;
     bool holds_gil = FALSE;
     PyReturn *pyreturn_values = NULL;
 
@@ -318,7 +324,6 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
         // TODO: free args and rcall
     }
 
-
     // first argument after the return contains the pointer to the sql_func 
structure
     if (sqlfun != NULL && sqlfun->ops->cnt > 0) {
         int cargs = pci->retc + 2;
@@ -748,23 +753,26 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
 
     {
         int pyret = 0;
-        PyObject *pFunc, *pModule;
+        PyObject *pFunc, *pModule, *str;
 
-        // TODO: does this create overhead?, see if we can share the import
-        pModule = PyImport_Import(PyString_FromString("__main__"));
+        str = PyString_FromString("__main__");
+        pModule = PyImport_Import(str);
+        Py_CLEAR(str);
+
         if (!Initialized)
         {
             VERBOSE_MESSAGE("Initializing function.\n");
+
             pyret = PyRun_SimpleString(pycall);
 
             Initialized = true;
         }
         pFunc = PyObject_GetAttrString(pModule, "pyfun");
-
         
 
         //fprintf(stdout, "%s\n", pycall);
         if (pyret != 0 || !pModule || !pFunc || !PyCallable_Check(pFunc)) {
+            PyErr_Print();
             msg = createException(MAL, "pyapi.eval", "could not parse Python 
code %s", pycall);
             goto wrapup;
         }
@@ -831,6 +839,8 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
         else
         {
             pResult = PyObject_CallObject(pFunc, pArgs);
+            Py_DECREF(pFunc);
+            Py_DECREF(pArgs);
         }
         if (PyErr_Occurred()) {
             PyObject *pErrType, *pErrVal, *pErrTb;
@@ -1196,9 +1206,9 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
             goto wrapup;
         }
     }
+    Py_DECREF(pResult);
 
-
-    ReleaseLock(gstate, &holds_gil, true);
+    //ReleaseLock(gstate, &holds_gil, true);
 
     VERBOSE_MESSAGE("Returning values.\n");
 
@@ -1287,6 +1297,9 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
     ReleaseLock(gstate, &holds_gil, true);
 
     GDKfree(pyreturn_values);
+    for (i = pci->retc + 2; i < pci->argc; i++)
+        if (args[i] != NULL)
+            GDKfree(args[i]);
     GDKfree(args);
     GDKfree(pycall);
     GDKfree(expr_ind);
@@ -1294,8 +1307,8 @@ str PyAPIeval(MalBlkPtr mb, MalStkPtr st
     VERBOSE_MESSAGE("Finished cleaning up.\n");
     return msg;
 }
-
-str PyAPIprelude(void *ret) {
+str
+ PyAPIprelude(void *ret) {
     (void) ret;
     MT_lock_init(&pyapiLock, "pyapi_lock");
     MT_lock_init(&pyapiSluice, "pyapi_sluice");
@@ -1428,17 +1441,26 @@ bool IsPyScalar(PyObject *object)
 
 bool IsPandasDataFrame(PyObject *object)
 {
-    return (strcmp(PyString_AsString(PyObject_Str(PyObject_Type(object))), 
"<class 'pandas.core.frame.DataFrame'>") == 0);
+    PyObject *str = PyObject_Str(PyObject_Type(object));
+    bool ret = strcmp(PyString_AsString(str), "<class 
'pandas.core.frame.DataFrame'>") == 0;
+    Py_DECREF(str);
+    return ret;
 }
 
 bool IsNPYArray(PyObject *object)
 {
-    return (strcmp(PyString_AsString(PyObject_Str(PyObject_Type(object))), 
"<type 'numpy.ndarray'>") == 0);
+    PyObject *str = PyObject_Str(PyObject_Type(object));
+    bool ret = strcmp(PyString_AsString(str), "<type 'numpy.ndarray'>") == 0;
+    Py_DECREF(str);
+    return ret;
 }
 
 bool IsNPYMaskedArray(PyObject *object)
 {
-    return (strcmp(PyString_AsString(PyObject_Str(PyObject_Type(object))), 
"<class 'numpy.ma.core.MaskedArray'>") == 0);
+    PyObject *str = PyObject_Str(PyObject_Type(object));
+    bool ret = strcmp(PyString_AsString(str), "<class 
'numpy.ma.core.MaskedArray'>") == 0;
+    Py_DECREF(str);
+    return ret;
 }
    
 int snprintf_huge(char * str, int size, hge x)
@@ -1512,7 +1534,7 @@ PyGILState_STATE AcquireLock(bool *holds
     if (*holds_gil == TRUE) 
     {
         VERBOSE_MESSAGE("Process already holds GIL!\n");
-        return 0;
+        return -1;
     }
 
     MT_lock_set(&pyapiLock, "pyapi.evaluate");
diff --git a/monetdb5/extras/pyapi/pyapi.mal b/monetdb5/extras/pyapi/pyapi.mal
--- a/monetdb5/extras/pyapi/pyapi.mal
+++ b/monetdb5/extras/pyapi/pyapi.mal
@@ -29,6 +29,7 @@ comment "grouped aggregates through Pyth
 command prelude() :void address PyAPIprelude;
 pyapi.prelude();
 
+
 # The SQL compiler needs these functions for bat-wise operations
 module batpyapi;
 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to