diff options
author | Uwe Hermann <uwe@hermann-uwe.de> | 2017-06-28 22:29:06 +0200 |
---|---|---|
committer | Uwe Hermann <uwe@hermann-uwe.de> | 2017-06-30 13:05:09 +0200 |
commit | 514b2edc54efda9c6698456748c4256bb901eddd (patch) | |
tree | 3a46086d63e37dec48fa0acedaa204513abb44ec /exception.c | |
parent | c1495906011ebabf97e799fe0f73e68ab0f1611a (diff) | |
download | libsigrokdecode-514b2edc54efda9c6698456748c4256bb901eddd.tar.gz libsigrokdecode-514b2edc54efda9c6698456748c4256bb901eddd.zip |
Acquire/release the Python GIL where needed to avoid threading issues.
With these additions, frontends can now call libsigrokdecode API
functions from different threads without running into threading issues.
The backend releases the GIL when it is performing tasks that might take
a while and it doesn't need to run Python/C API calls during that time.
This allows frontends to run multiple PD stacks (in multiple frontend
threads) "at the same time" in a time-sharing, "interlocked" manner.
Whenever one of the decoders is inside e.g. self.wait() it releases the
GIL and thus allows other decoders to do some work in the mean time.
The user-visible effect is that for use-cases such as running 3 different
decoder stacks at the same time for an acquisition, the user will not
have to wait for PD 1 to finish decoding, then wait for PD 2 to finish
decoding, and only *then* being able to see annotations from PD 3.
Instead, all three PDs will decode some chunks of data from time to
time, thus the user is able to inspect annotations from all 3 PDs while
the acquisition and decoding is still going on.
Diffstat (limited to 'exception.c')
-rw-r--r-- | exception.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/exception.c b/exception.c index 7027df5..b440758 100644 --- a/exception.c +++ b/exception.c @@ -28,6 +28,8 @@ static char *py_stringify(PyObject *py_obj) PyObject *py_str, *py_bytes; char *str = NULL; + /* Note: Caller already ran PyGILState_Ensure(). */ + if (!py_obj) return NULL; @@ -56,6 +58,8 @@ static char *py_get_string_attr(PyObject *py_obj, const char *attr) PyObject *py_str, *py_bytes; char *str = NULL; + /* Note: Caller already ran PyGILState_Ensure(). */ + if (!py_obj) return NULL; @@ -87,6 +91,7 @@ SRD_PRIV void srd_exception_catch(const char *format, ...) PyObject *py_mod, *py_func, *py_tracefmt; char *msg, *etype_name, *evalue_str, *tracefmt_str; const char *etype_name_fallback; + PyGILState_STATE gstate; py_etype = py_evalue = py_etraceback = py_mod = py_func = NULL; @@ -94,6 +99,8 @@ SRD_PRIV void srd_exception_catch(const char *format, ...) msg = g_strdup_vprintf(format, args); va_end(args); + gstate = PyGILState_Ensure(); + PyErr_Fetch(&py_etype, &py_evalue, &py_etraceback); if (!py_etype) { /* No current exception, so just print the message. */ @@ -151,5 +158,7 @@ cleanup: /* Just in case. */ PyErr_Clear(); + PyGILState_Release(gstate); + g_free(msg); } |