]> git.ipfire.org Git - people/ms/pakfire.git/blobdiff - src/_pakfire/pakfire.c
python: Make sure we hold the GIL when jumping into the logging callback
[people/ms/pakfire.git] / src / _pakfire / pakfire.c
index 16b745a7258194e59f02c9dcb826f4357f92fb39..b82f28a54250ce2aa4593077b253c7062714b938 100644 (file)
@@ -424,29 +424,39 @@ static PyObject* Pakfire_version_compare(PakfireObject* self, PyObject* args) {
 static int Pakfire_execute_output_callback(struct pakfire_ctx* ctx, struct pakfire_jail* jail,
                void* data, const char* line, size_t length) {
        PyObject* callback = (PyObject*)data;
-       int r = 0;
+       PyObject* args = NULL;
+       PyObject* result = NULL;
+       int r = 1;
 
        // Do nothing if callback isn't set
        if (!callback)
                return 0;
 
        // Remove the trailing newline
-       if (line && line[length - 1] == '\n')
+       if (line && length && line[length - 1] == '\n')
                length--;
 
+       // Get the GIL
+       PyGILState_STATE state = PyGILState_Ensure();
+
        // Create tuple with arguments for the callback function
-       PyObject* args = Py_BuildValue("(is#)", LOG_INFO, line, (Py_ssize_t)length);
+       args = Py_BuildValue("(is#)", LOG_INFO, line, (Py_ssize_t)length);
        if (!args)
-               return 1;
+               goto ERROR;
 
-       PyObject* result = PyObject_CallObject(callback, args);
+       // Call the callback method
+       result = PyObject_CallObject(callback, args);
     if (result && PyLong_Check(result)) {
         r = PyLong_AsLong(result);
     }
 
+ERROR:
        Py_XDECREF(args);
        Py_XDECREF(result);
 
+       // Release the GIL
+       PyGILState_Release(state);
+
        return r;
 }
 
@@ -500,7 +510,7 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
 
                if (!PyUnicode_Check(item)) {
                        PyErr_Format(PyExc_TypeError, "Item %u in command is not a string", i);
-                       return NULL;
+                       goto ERROR;
                }
 
                // Copy to argv
@@ -526,12 +536,6 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
                goto ERROR;
        }
 
-       // Check callback
-       if (callback && !PyCallable_Check(callback)) {
-               PyErr_SetString(PyExc_TypeError, "callback must be callable\n");
-               goto ERROR;
-       }
-
        // Set nice
        if (nice) {
                r = pakfire_jail_nice(jail, nice);
@@ -569,32 +573,34 @@ static PyObject* Pakfire_execute(PakfireObject* self, PyObject* args, PyObject*
                }
        }
 
-       const Py_ssize_t num_bind = PySequence_Length(bind);
-
        // Bind
-       for (unsigned int i = 0; i < num_bind; i++) {
-               PyObject* b = PySequence_ITEM(bind, i);
-               if (!b)
-                       goto ERROR;
+       if (bind && PySequence_Check(bind)) {
+               const Py_ssize_t num_bind = PySequence_Length(bind);
 
-               // Check if this is a Unicode object
-               if (!PyUnicode_Check(b)) {
-                       PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
-                       Py_DECREF(b);
-                       goto ERROR;
-               }
+               for (unsigned int i = 0; i < num_bind; i++) {
+                       PyObject* b = PySequence_ITEM(bind, i);
+                       if (!b)
+                               goto ERROR;
+
+                       // Check if this is a Unicode object
+                       if (!PyUnicode_Check(b)) {
+                               PyErr_SetString(PyExc_ValueError, "bind contains a non-Unicode object");
+                               Py_DECREF(b);
+                               goto ERROR;
+                       }
 
-               const char* path = PyUnicode_AsUTF8(b);
+                       const char* path = PyUnicode_AsUTF8(b);
+
+                       // Perform bind
+                       r = pakfire_jail_bind(jail, path, path, 0);
+                       if (r) {
+                               PyErr_SetFromErrno(PyExc_OSError);
+                               Py_DECREF(b);
+                               goto ERROR;
+                       }
 
-               // Perform bind
-               r = pakfire_jail_bind(jail, path, path, 0);
-               if (r) {
-                       PyErr_SetFromErrno(PyExc_OSError);
                        Py_DECREF(b);
-                       goto ERROR;
                }
-
-               Py_DECREF(b);
        }
 
        Py_BEGIN_ALLOW_THREADS