Sam Eiderman
2019-Nov-18 12:38 UTC
[Libguestfs] [PATCH] Python: Fix GIL usage in guestfs_int_py_event_callback_wrapper (RHBZ#1773520)
All Py_* functions should be protected by the GIL. Otherwise internal python data structures can get corrupted. Move PyGILState_Ensure to the beginning of the block and PyGILState_Release to the bottom. Signed-off-by: Sam Eiderman <sameid@google.com> --- python/handle.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/python/handle.c b/python/handle.c index ffd0794d8..659bb5b06 100644 --- a/python/handle.c +++ b/python/handle.c @@ -112,13 +112,17 @@ guestfs_int_py_event_callback_wrapper (guestfs_h *g, const char *buf, size_t buf_len, const uint64_t *array, size_t array_len) { - PyGILState_STATE py_save = PyGILState_UNLOCKED; + PyGILState_STATE py_save; PyObject *py_callback = callback; PyObject *py_array; PyObject *args; PyObject *a; size_t i; PyObject *py_r; + int threads_initialized = PyEval_ThreadsInitialized (); + + if (threads_initialized) + py_save = PyGILState_Ensure (); py_array = PyList_New (array_len); for (i = 0; i < array_len; ++i) { @@ -132,14 +136,8 @@ guestfs_int_py_event_callback_wrapper (guestfs_h *g, buf, buf_len, py_array); Py_INCREF (args); - if (PyEval_ThreadsInitialized ()) - py_save = PyGILState_Ensure (); - py_r = PyObject_CallObject (py_callback, args); - if (PyEval_ThreadsInitialized ()) - PyGILState_Release (py_save); - Py_DECREF (args); if (py_r != NULL) @@ -147,6 +145,9 @@ guestfs_int_py_event_callback_wrapper (guestfs_h *g, else /* Callback threw an exception: print it. */ PyErr_PrintEx (0); + + if (threads_initialized) + PyGILState_Release (py_save); } PyObject * -- 2.24.0.432.g9d3f5f5b63-goog
Possibly Parallel Threads
- [PATCH 1/2] python: Avoid crash if callback parameters cannot be built
- [PATCH 1/2] python: Avoid crash if callback parameters cannot be built
- [PATCH] python: Avoid leaking py_array along error paths
- [PATCH v3 0/2] python: Avoid leaking py_array and py_args in event callbacks
- [PATCH 2/2] python: Use bytes instead of str for event callback buffer