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.
static void decoder_free(struct srd_decoder *dec)
{
static void decoder_free(struct srd_decoder *dec)
{
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
Py_XDECREF(dec->py_dec);
Py_XDECREF(dec->py_mod);
Py_XDECREF(dec->py_dec);
Py_XDECREF(dec->py_mod);
+ PyGILState_Release(gstate);
g_slist_free_full(dec->options, &decoder_option_free);
g_slist_free_full(dec->binary, (GDestroyNotify)&g_strfreev);
g_slist_free_full(dec->options, &decoder_option_free);
g_slist_free_full(dec->binary, (GDestroyNotify)&g_strfreev);
struct srd_channel *pdch;
GSList *pdchl;
ssize_t i;
struct srd_channel *pdch;
GSList *pdchl;
ssize_t i;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
- if (!PyObject_HasAttrString(d->py_dec, attr))
+ if (!PyObject_HasAttrString(d->py_dec, attr)) {
/* No channels of this type specified. */
/* No channels of this type specified. */
+ PyGILState_Release(gstate);
Py_DECREF(py_channellist);
*out_pdchl = pdchl;
Py_DECREF(py_channellist);
*out_pdchl = pdchl;
+ PyGILState_Release(gstate);
+
return SRD_OK;
except_out:
return SRD_OK;
except_out:
err_out:
g_slist_free_full(pdchl, &channel_free);
Py_XDECREF(py_channellist);
err_out:
g_slist_free_full(pdchl, &channel_free);
Py_XDECREF(py_channellist);
+ PyGILState_Release(gstate);
struct srd_decoder_option *o;
GVariant *gvar;
ssize_t opt, i;
struct srd_decoder_option *o;
GVariant *gvar;
ssize_t opt, i;
+ PyGILState_STATE gstate;
- if (!PyObject_HasAttrString(d->py_dec, "options"))
+ gstate = PyGILState_Ensure();
+
+ if (!PyObject_HasAttrString(d->py_dec, "options")) {
/* No options, that's fine. */
/* No options, that's fine. */
+ PyGILState_Release(gstate);
}
d->options = options;
Py_DECREF(py_opts);
}
d->options = options;
Py_DECREF(py_opts);
+ PyGILState_Release(gstate);
err_out:
g_slist_free_full(options, &decoder_option_free);
Py_XDECREF(py_opts);
err_out:
g_slist_free_full(options, &decoder_option_free);
Py_XDECREF(py_opts);
+ PyGILState_Release(gstate);
GSList *annotations;
char **annpair;
ssize_t i;
GSList *annotations;
char **annpair;
ssize_t i;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
- if (!PyObject_HasAttrString(dec->py_dec, "annotations"))
+ if (!PyObject_HasAttrString(dec->py_dec, "annotations")) {
+ PyGILState_Release(gstate);
}
dec->annotations = annotations;
Py_DECREF(py_annlist);
}
dec->annotations = annotations;
Py_DECREF(py_annlist);
+ PyGILState_Release(gstate);
err_out:
g_slist_free_full(annotations, (GDestroyNotify)&g_strfreev);
Py_XDECREF(py_annlist);
err_out:
g_slist_free_full(annotations, (GDestroyNotify)&g_strfreev);
Py_XDECREF(py_annlist);
+ PyGILState_Release(gstate);
struct srd_decoder_annotation_row *ann_row;
ssize_t i, k;
size_t class_idx;
struct srd_decoder_annotation_row *ann_row;
ssize_t i, k;
size_t class_idx;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
- if (!PyObject_HasAttrString(dec->py_dec, "annotation_rows"))
+ if (!PyObject_HasAttrString(dec->py_dec, "annotation_rows")) {
+ PyGILState_Release(gstate);
}
dec->annotation_rows = annotation_rows;
Py_DECREF(py_ann_rows);
}
dec->annotation_rows = annotation_rows;
Py_DECREF(py_ann_rows);
+ PyGILState_Release(gstate);
err_out:
g_slist_free_full(annotation_rows, &annotation_row_free);
Py_XDECREF(py_ann_rows);
err_out:
g_slist_free_full(annotation_rows, &annotation_row_free);
Py_XDECREF(py_ann_rows);
+ PyGILState_Release(gstate);
GSList *bin_classes;
char **bin;
ssize_t i;
GSList *bin_classes;
char **bin;
ssize_t i;
+ PyGILState_STATE gstate;
- if (!PyObject_HasAttrString(dec->py_dec, "binary"))
+ gstate = PyGILState_Ensure();
+
+ if (!PyObject_HasAttrString(dec->py_dec, "binary")) {
+ PyGILState_Release(gstate);
}
dec->binary = bin_classes;
Py_DECREF(py_bin_classes);
}
dec->binary = bin_classes;
Py_DECREF(py_bin_classes);
+ PyGILState_Release(gstate);
err_out:
g_slist_free_full(bin_classes, (GDestroyNotify)&g_strfreev);
Py_XDECREF(py_bin_classes);
err_out:
g_slist_free_full(bin_classes, (GDestroyNotify)&g_strfreev);
Py_XDECREF(py_bin_classes);
+ PyGILState_Release(gstate);
{
PyObject *py_method;
int is_callable;
{
PyObject *py_method;
int is_callable;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
py_method = PyObject_GetAttrString(py_dec, method_name);
if (!py_method) {
srd_exception_catch("Protocol decoder %s Decoder class "
"has no %s() method", mod_name, method_name);
py_method = PyObject_GetAttrString(py_dec, method_name);
if (!py_method) {
srd_exception_catch("Protocol decoder %s Decoder class "
"has no %s() method", mod_name, method_name);
+ PyGILState_Release(gstate);
return SRD_ERR_PYTHON;
}
is_callable = PyCallable_Check(py_method);
Py_DECREF(py_method);
return SRD_ERR_PYTHON;
}
is_callable = PyCallable_Check(py_method);
Py_DECREF(py_method);
+ PyGILState_Release(gstate);
+
if (!is_callable) {
srd_err("Protocol decoder %s Decoder class attribute '%s' "
"is not a method.", mod_name, method_name);
if (!is_callable) {
srd_err("Protocol decoder %s Decoder class attribute '%s' "
"is not a method.", mod_name, method_name);
{
PyObject *py_apiver;
long apiver;
{
PyObject *py_apiver;
long apiver;
+ PyGILState_STATE gstate;
+ gstate = PyGILState_Ensure();
+
py_apiver = PyObject_GetAttrString(d->py_dec, "api_version");
apiver = (py_apiver && PyLong_Check(py_apiver))
? PyLong_AsLong(py_apiver) : 0;
Py_XDECREF(py_apiver);
py_apiver = PyObject_GetAttrString(d->py_dec, "api_version");
apiver = (py_apiver && PyLong_Check(py_apiver))
? PyLong_AsLong(py_apiver) : 0;
Py_XDECREF(py_apiver);
+ PyGILState_Release(gstate);
+
long apiver;
int is_subclass;
const char *fail_txt;
long apiver;
int is_subclass;
const char *fail_txt;
+ PyGILState_STATE gstate;
if (!srd_check_init())
return SRD_ERR;
if (!srd_check_init())
return SRD_ERR;
if (!module_name)
return SRD_ERR_ARG;
if (!module_name)
return SRD_ERR_ARG;
+ gstate = PyGILState_Ensure();
+
if (PyDict_GetItemString(PyImport_GetModuleDict(), module_name)) {
/* Module was already imported. */
if (PyDict_GetItemString(PyImport_GetModuleDict(), module_name)) {
/* Module was already imported. */
+ PyGILState_Release(gstate);
+ PyGILState_Release(gstate);
+
/* Append it to the list of loaded decoders. */
pd_list = g_slist_append(pd_list, d);
/* Append it to the list of loaded decoders. */
pd_list = g_slist_append(pd_list, d);
if (fail_txt)
srd_err("Failed to load decoder %s: %s", module_name, fail_txt);
decoder_free(d);
if (fail_txt)
srd_err("Failed to load decoder %s: %s", module_name, fail_txt);
decoder_free(d);
+ PyGILState_Release(gstate);
{
PyObject *py_str;
char *doc;
{
PyObject *py_str;
char *doc;
+ PyGILState_STATE gstate;
if (!srd_check_init())
return NULL;
if (!srd_check_init())
return NULL;
+ gstate = PyGILState_Ensure();
+
if (!PyObject_HasAttrString(dec->py_mod, "__doc__"))
if (!PyObject_HasAttrString(dec->py_mod, "__doc__"))
if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) {
srd_exception_catch("Failed to get docstring");
if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) {
srd_exception_catch("Failed to get docstring");
py_str_as_str(py_str, &doc);
Py_DECREF(py_str);
py_str_as_str(py_str, &doc);
Py_DECREF(py_str);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return NULL;
Py_ssize_t pos = 0;
char *prefix;
size_t prefix_len;
Py_ssize_t pos = 0;
char *prefix;
size_t prefix_len;
+ PyGILState_STATE gstate;
set = files = prefix_obj = zipimporter = zipimporter_class = NULL;
set = files = prefix_obj = zipimporter = zipimporter_class = NULL;
+ gstate = PyGILState_Ensure();
+
zipimport_mod = py_import_by_name("zipimport");
if (zipimport_mod == NULL)
goto err_out;
zipimport_mod = py_import_by_name("zipimport");
if (zipimport_mod == NULL)
goto err_out;
Py_XDECREF(zipimporter_class);
Py_XDECREF(zipimport_mod);
PyErr_Clear();
Py_XDECREF(zipimporter_class);
Py_XDECREF(zipimport_mod);
PyErr_Clear();
+ PyGILState_Release(gstate);
}
static void srd_decoder_load_all_path(char *path)
}
static void srd_decoder_load_all_path(char *path)
PyObject *py_str, *py_bytes;
char *str = NULL;
PyObject *py_str, *py_bytes;
char *str = NULL;
+ /* Note: Caller already ran PyGILState_Ensure(). */
+
if (!py_obj)
return NULL;
if (!py_obj)
return NULL;
PyObject *py_str, *py_bytes;
char *str = NULL;
PyObject *py_str, *py_bytes;
char *str = NULL;
+ /* Note: Caller already ran PyGILState_Ensure(). */
+
if (!py_obj)
return NULL;
if (!py_obj)
return NULL;
PyObject *py_mod, *py_func, *py_tracefmt;
char *msg, *etype_name, *evalue_str, *tracefmt_str;
const char *etype_name_fallback;
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;
py_etype = py_evalue = py_etraceback = py_mod = py_func = NULL;
msg = g_strdup_vprintf(format, args);
va_end(args);
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. */
PyErr_Fetch(&py_etype, &py_evalue, &py_etraceback);
if (!py_etype) {
/* No current exception, so just print the message. */
/* Just in case. */
PyErr_Clear();
/* Just in case. */
PyErr_Clear();
+ PyGILState_Release(gstate);
+
gint64 val_int;
int ret;
const char *val_str;
gint64 val_int;
int ret;
const char *val_str;
+ PyGILState_STATE gstate;
if (!di) {
srd_err("Invalid decoder instance.");
if (!di) {
srd_err("Invalid decoder instance.");
+ gstate = PyGILState_Ensure();
+
if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) {
/* Decoder has no options. */
if (!PyObject_HasAttrString(di->decoder->py_dec, "options")) {
/* Decoder has no options. */
+ PyGILState_Release(gstate);
if (g_hash_table_size(options) == 0) {
/* No options provided. */
return SRD_OK;
if (g_hash_table_size(options) == 0) {
/* No options provided. */
return SRD_OK;
srd_exception_catch("Stray exception in srd_inst_option_set()");
ret = SRD_ERR_PYTHON;
}
srd_exception_catch("Stray exception in srd_inst_option_set()");
ret = SRD_ERR_PYTHON;
}
+ PyGILState_Release(gstate);
struct srd_decoder *dec;
struct srd_decoder_inst *di;
char *inst_id;
struct srd_decoder *dec;
struct srd_decoder_inst *di;
char *inst_id;
+ PyGILState_STATE gstate;
i = 1;
srd_dbg("Creating new %s instance.", decoder_id);
i = 1;
srd_dbg("Creating new %s instance.", decoder_id);
memset(di->old_pins_array->data, SRD_INITIAL_PIN_SAME_AS_SAMPLE0,
di->dec_num_channels);
memset(di->old_pins_array->data, SRD_INITIAL_PIN_SAME_AS_SAMPLE0,
di->dec_num_channels);
+ gstate = PyGILState_Ensure();
+
/* Create a new instance of this decoder class. */
if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) {
if (PyErr_Occurred())
srd_exception_catch("Failed to create %s instance",
decoder_id);
/* Create a new instance of this decoder class. */
if (!(di->py_inst = PyObject_CallObject(dec->py_dec, NULL))) {
if (PyErr_Occurred())
srd_exception_catch("Failed to create %s instance",
decoder_id);
+ PyGILState_Release(gstate);
g_free(di->dec_channelmap);
g_free(di);
return NULL;
}
g_free(di->dec_channelmap);
g_free(di);
return NULL;
}
+ PyGILState_Release(gstate);
+
if (options && srd_inst_option_set(di, options) != SRD_OK) {
g_free(di->dec_channelmap);
g_free(di);
if (options && srd_inst_option_set(di, options) != SRD_OK) {
g_free(di->dec_channelmap);
g_free(di);
struct srd_decoder_inst *di_bottom,
struct srd_decoder_inst *di_top)
{
struct srd_decoder_inst *di_bottom,
struct srd_decoder_inst *di_top)
{
if (session_is_valid(sess) != SRD_OK) {
srd_err("Invalid session.");
return SRD_ERR_ARG;
if (session_is_valid(sess) != SRD_OK) {
srd_err("Invalid session.");
return SRD_ERR_ARG;
GSList *l;
struct srd_decoder_inst *next_di;
int ret;
GSList *l;
struct srd_decoder_inst *next_di;
int ret;
+ PyGILState_STATE gstate;
srd_dbg("Calling start() method on protocol decoder instance %s.",
di->inst_id);
srd_dbg("Calling start() method on protocol decoder instance %s.",
di->inst_id);
+ gstate = PyGILState_Ensure();
+
/* Run self.start(). */
if (!(py_res = PyObject_CallMethod(di->py_inst, "start", NULL))) {
srd_exception_catch("Protocol decoder instance %s",
di->inst_id);
/* Run self.start(). */
if (!(py_res = PyObject_CallMethod(di->py_inst, "start", NULL))) {
srd_exception_catch("Protocol decoder instance %s",
di->inst_id);
+ PyGILState_Release(gstate);
return SRD_ERR_PYTHON;
}
Py_DecRef(py_res);
return SRD_ERR_PYTHON;
}
Py_DecRef(py_res);
/* Set self.matched to None. */
PyObject_SetAttrString(di->py_inst, "matched", Py_None);
/* Set self.matched to None. */
PyObject_SetAttrString(di->py_inst, "matched", Py_None);
+ PyGILState_Release(gstate);
+
/* Start all the PDs stacked on top of this one. */
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
/* Start all the PDs stacked on top of this one. */
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
PyObject *py_res;
struct srd_decoder_inst *di;
int wanted_term;
PyObject *py_res;
struct srd_decoder_inst *di;
int wanted_term;
+ PyGILState_STATE gstate;
srd_dbg("%s: Starting thread routine for decoder.", di->inst_id);
srd_dbg("%s: Starting thread routine for decoder.", di->inst_id);
+ gstate = PyGILState_Ensure();
+
/*
* Call self.decode(). Only returns if the PD throws an exception.
* "Regular" termination of the decode() method is not expected.
/*
* Call self.decode(). Only returns if the PD throws an exception.
* "Regular" termination of the decode() method is not expected.
*/
srd_dbg("%s: Thread done (!res, want_term).", di->inst_id);
PyErr_Clear();
*/
srd_dbg("%s: Thread done (!res, want_term).", di->inst_id);
PyErr_Clear();
+ PyGILState_Release(gstate);
return NULL;
}
if (!py_res) {
return NULL;
}
if (!py_res) {
srd_dbg("%s: decode() terminated unrequested.", di->inst_id);
srd_exception_catch("Protocol decoder instance %s: ", di->inst_id);
srd_dbg("%s: Thread done (!res, !want_term).", di->inst_id);
srd_dbg("%s: decode() terminated unrequested.", di->inst_id);
srd_exception_catch("Protocol decoder instance %s: ", di->inst_id);
srd_dbg("%s: Thread done (!res, !want_term).", di->inst_id);
+ PyGILState_Release(gstate);
Py_DecRef(py_res);
PyErr_Clear();
Py_DecRef(py_res);
PyErr_Clear();
+ PyGILState_Release(gstate);
+
srd_dbg("%s: Thread done (with res).", di->inst_id);
return NULL;
srd_dbg("%s: Thread done (with res).", di->inst_id);
return NULL;
{
GSList *l;
struct srd_pd_output *pdo;
{
GSList *l;
struct srd_pd_output *pdo;
+ PyGILState_STATE gstate;
srd_dbg("Freeing instance %s", di->inst_id);
srd_inst_join_decode_thread(di);
srd_dbg("Freeing instance %s", di->inst_id);
srd_inst_join_decode_thread(di);
srd_inst_reset_state(di);
srd_inst_reset_state(di);
+ gstate = PyGILState_Ensure();
+ PyGILState_Release(gstate);
+
g_free(di->inst_id);
g_free(di->dec_channelmap);
g_free(di->channel_samples);
g_free(di->inst_id);
g_free(di->dec_channelmap);
g_free(di->channel_samples);
PyMODINIT_FUNC PyInit_sigrokdecode(void)
{
PyObject *mod, *Decoder_type;
PyMODINIT_FUNC PyInit_sigrokdecode(void)
{
PyObject *mod, *Decoder_type;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
mod = PyModule_Create(&sigrokdecode_module);
if (!mod)
mod = PyModule_Create(&sigrokdecode_module);
if (!mod)
+ PyGILState_Release(gstate);
+
return mod;
err_out:
Py_XDECREF(mod);
srd_exception_catch("Failed to initialize module");
return mod;
err_out:
Py_XDECREF(mod);
srd_exception_catch("Failed to initialize module");
+ PyGILState_Release(gstate);
GSList *l;
struct srd_decoder_inst *next_di;
int ret;
GSList *l;
struct srd_decoder_inst *next_di;
int ret;
+ PyGILState_STATE gstate;
if (key != SRD_CONF_SAMPLERATE)
/* This is the only key we pass on to the decoder for now. */
return SRD_OK;
if (key != SRD_CONF_SAMPLERATE)
/* This is the only key we pass on to the decoder for now. */
return SRD_OK;
+ gstate = PyGILState_Ensure();
+
if (PyObject_HasAttrString(di->py_inst, "metadata")) {
py_ret = PyObject_CallMethod(di->py_inst, "metadata", "lK",
(long)SRD_CONF_SAMPLERATE,
if (PyObject_HasAttrString(di->py_inst, "metadata")) {
py_ret = PyObject_CallMethod(di->py_inst, "metadata", "lK",
(long)SRD_CONF_SAMPLERATE,
+ PyGILState_Release(gstate);
+
/* Push metadata to all the PDs stacked on top of this one. */
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
/* Push metadata to all the PDs stacked on top of this one. */
for (l = di->next_di; l; l = l->next) {
next_di = l->data;
+ /* Initialize the Python GIL (this also happens to acquire it). */
+ PyEval_InitThreads();
+
+ /* Release the GIL (ignore return value, we don't need it here). */
+ (void)PyEval_SaveThread();
+
max_session_id = 0;
return SRD_OK;
max_session_id = 0;
return SRD_OK;
g_slist_free_full(searchpaths, g_free);
searchpaths = NULL;
g_slist_free_full(searchpaths, g_free);
searchpaths = NULL;
+ /*
+ * Acquire the GIL, otherwise Py_Finalize() might have issues.
+ * Ignore the return value, we don't need it here.
+ */
+ (void)PyGILState_Ensure();
+
/* Py_Finalize() returns void, any finalization errors are ignored. */
Py_Finalize();
/* Py_Finalize() returns void, any finalization errors are ignored. */
Py_Finalize();
+ /* Note: No need to release the GIL since Python is shut down now. */
+
max_session_id = -1;
return SRD_OK;
max_session_id = -1;
return SRD_OK;
SRD_PRIV int srd_decoder_searchpath_add(const char *path)
{
PyObject *py_cur_path, *py_item;
SRD_PRIV int srd_decoder_searchpath_add(const char *path)
{
PyObject *py_cur_path, *py_item;
+ PyGILState_STATE gstate;
srd_dbg("Adding '%s' to module path.", path);
srd_dbg("Adding '%s' to module path.", path);
+ gstate = PyGILState_Ensure();
+
py_cur_path = PySys_GetObject("path");
if (!py_cur_path)
py_cur_path = PySys_GetObject("path");
if (!py_cur_path)
py_item = PyUnicode_FromString(path);
if (!py_item) {
srd_exception_catch("Failed to create Unicode object");
py_item = PyUnicode_FromString(path);
if (!py_item) {
srd_exception_catch("Failed to create Unicode object");
}
if (PyList_Insert(py_cur_path, 0, py_item) < 0) {
srd_exception_catch("Failed to insert path element");
Py_DECREF(py_item);
}
if (PyList_Insert(py_cur_path, 0, py_item) < 0) {
srd_exception_catch("Failed to insert path element");
Py_DECREF(py_item);
+ PyGILState_Release(gstate);
+
searchpaths = g_slist_prepend(searchpaths, g_strdup(path));
return SRD_OK;
searchpaths = g_slist_prepend(searchpaths, g_strdup(path));
return SRD_OK;
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
struct srd_proto_data_annotation *pda;
int ann_class;
char **ann_text;
struct srd_proto_data_annotation *pda;
int ann_class;
char **ann_text;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
/* Should be a list of [annotation class, [string, ...]]. */
if (!PyList_Check(obj)) {
srd_err("Protocol decoder %s submitted an annotation that"
" is not a list", di->decoder->name);
/* Should be a list of [annotation class, [string, ...]]. */
if (!PyList_Check(obj)) {
srd_err("Protocol decoder %s submitted an annotation that"
" is not a list", di->decoder->name);
}
/* Should have 2 elements. */
}
/* Should have 2 elements. */
srd_err("Protocol decoder %s submitted annotation list with "
"%zd elements instead of 2", di->decoder->name,
PyList_Size(obj));
srd_err("Protocol decoder %s submitted annotation list with "
"%zd elements instead of 2", di->decoder->name,
PyList_Size(obj));
if (!PyLong_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted annotation list, but "
"first element was not an integer.", di->decoder->name);
if (!PyLong_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted annotation list, but "
"first element was not an integer.", di->decoder->name);
}
ann_class = PyLong_AsLong(py_tmp);
if (!(pdo = g_slist_nth_data(di->decoder->annotations, ann_class))) {
srd_err("Protocol decoder %s submitted data to unregistered "
"annotation class %d.", di->decoder->name, ann_class);
}
ann_class = PyLong_AsLong(py_tmp);
if (!(pdo = g_slist_nth_data(di->decoder->annotations, ann_class))) {
srd_err("Protocol decoder %s submitted data to unregistered "
"annotation class %d.", di->decoder->name, ann_class);
}
/* Second element must be a list. */
}
/* Second element must be a list. */
if (!PyList_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted annotation list, but "
"second element was not a list.", di->decoder->name);
if (!PyList_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted annotation list, but "
"second element was not a list.", di->decoder->name);
}
if (py_strseq_to_char(py_tmp, &ann_text) != SRD_OK) {
srd_err("Protocol decoder %s submitted annotation list, but "
"second element was malformed.", di->decoder->name);
}
if (py_strseq_to_char(py_tmp, &ann_text) != SRD_OK) {
srd_err("Protocol decoder %s submitted annotation list, but "
"second element was malformed.", di->decoder->name);
}
pda = g_malloc(sizeof(struct srd_proto_data_annotation));
}
pda = g_malloc(sizeof(struct srd_proto_data_annotation));
pda->ann_text = ann_text;
pdata->data = pda;
pda->ann_text = ann_text;
pdata->data = pda;
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
}
static int convert_binary(struct srd_decoder_inst *di, PyObject *obj,
}
static int convert_binary(struct srd_decoder_inst *di, PyObject *obj,
Py_ssize_t size;
int bin_class;
char *class_name, *buf;
Py_ssize_t size;
int bin_class;
char *class_name, *buf;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
/* Should be a list of [binary class, bytes]. */
if (!PyList_Check(obj)) {
srd_err("Protocol decoder %s submitted non-list for SRD_OUTPUT_BINARY.",
di->decoder->name);
/* Should be a list of [binary class, bytes]. */
if (!PyList_Check(obj)) {
srd_err("Protocol decoder %s submitted non-list for SRD_OUTPUT_BINARY.",
di->decoder->name);
}
/* Should have 2 elements. */
}
/* Should have 2 elements. */
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list "
"with %zd elements instead of 2", di->decoder->name,
PyList_Size(obj));
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list "
"with %zd elements instead of 2", di->decoder->name,
PyList_Size(obj));
}
/* The first element should be an integer. */
}
/* The first element should be an integer. */
if (!PyLong_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list, "
"but first element was not an integer.", di->decoder->name);
if (!PyLong_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list, "
"but first element was not an integer.", di->decoder->name);
}
bin_class = PyLong_AsLong(py_tmp);
if (!(class_name = g_slist_nth_data(di->decoder->binary, bin_class))) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY with "
"unregistered binary class %d.", di->decoder->name, bin_class);
}
bin_class = PyLong_AsLong(py_tmp);
if (!(class_name = g_slist_nth_data(di->decoder->binary, bin_class))) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY with "
"unregistered binary class %d.", di->decoder->name, bin_class);
}
/* Second element should be bytes. */
}
/* Second element should be bytes. */
if (!PyBytes_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list, "
"but second element was not bytes.", di->decoder->name);
if (!PyBytes_Check(py_tmp)) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list, "
"but second element was not bytes.", di->decoder->name);
}
/* Consider an empty set of bytes a bug. */
if (PyBytes_Size(py_tmp) == 0) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY "
"with empty data set.", di->decoder->name);
}
/* Consider an empty set of bytes a bug. */
if (PyBytes_Size(py_tmp) == 0) {
srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY "
"with empty data set.", di->decoder->name);
}
pdb = g_malloc(sizeof(struct srd_proto_data_binary));
if (PyBytes_AsStringAndSize(py_tmp, &buf, &size) == -1)
}
pdb = g_malloc(sizeof(struct srd_proto_data_binary));
if (PyBytes_AsStringAndSize(py_tmp, &buf, &size) == -1)
+ goto err;
+
+ PyGILState_Release(gstate);
+
pdb->bin_class = bin_class;
pdb->size = size;
if (!(pdb->data = g_try_malloc(pdb->size)))
pdb->bin_class = bin_class;
pdb->size = size;
if (!(pdb->data = g_try_malloc(pdb->size)))
pdata->data = pdb;
return SRD_OK;
pdata->data = pdb;
return SRD_OK;
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
}
static int convert_meta(struct srd_proto_data *pdata, PyObject *obj)
{
long long intvalue;
double dvalue;
}
static int convert_meta(struct srd_proto_data *pdata, PyObject *obj)
{
long long intvalue;
double dvalue;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (pdata->pdo->meta_type == G_VARIANT_TYPE_INT64) {
if (!PyLong_Check(obj)) {
PyErr_Format(PyExc_TypeError, "This output was registered "
"as 'int', but something else was passed.");
if (pdata->pdo->meta_type == G_VARIANT_TYPE_INT64) {
if (!PyLong_Check(obj)) {
PyErr_Format(PyExc_TypeError, "This output was registered "
"as 'int', but something else was passed.");
}
intvalue = PyLong_AsLongLong(obj);
if (PyErr_Occurred())
}
intvalue = PyLong_AsLongLong(obj);
if (PyErr_Occurred())
pdata->data = g_variant_new_int64(intvalue);
} else if (pdata->pdo->meta_type == G_VARIANT_TYPE_DOUBLE) {
if (!PyFloat_Check(obj)) {
PyErr_Format(PyExc_TypeError, "This output was registered "
"as 'float', but something else was passed.");
pdata->data = g_variant_new_int64(intvalue);
} else if (pdata->pdo->meta_type == G_VARIANT_TYPE_DOUBLE) {
if (!PyFloat_Check(obj)) {
PyErr_Format(PyExc_TypeError, "This output was registered "
"as 'float', but something else was passed.");
}
dvalue = PyFloat_AsDouble(obj);
if (PyErr_Occurred())
}
dvalue = PyFloat_AsDouble(obj);
if (PyErr_Occurred())
pdata->data = g_variant_new_double(dvalue);
}
pdata->data = g_variant_new_double(dvalue);
}
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
}
static PyObject *Decoder_put(PyObject *self, PyObject *args)
}
static PyObject *Decoder_put(PyObject *self, PyObject *args)
uint64_t start_sample, end_sample;
int output_id;
struct srd_pd_callback *cb;
uint64_t start_sample, end_sample;
int output_id;
struct srd_pd_callback *cb;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!(di = srd_inst_find_by_obj(NULL, self))) {
/* Shouldn't happen. */
srd_dbg("put(): self instance not found.");
if (!(di = srd_inst_find_by_obj(NULL, self))) {
/* Shouldn't happen. */
srd_dbg("put(): self instance not found.");
}
if (!PyArg_ParseTuple(args, "KKiO", &start_sample, &end_sample,
}
if (!PyArg_ParseTuple(args, "KKiO", &start_sample, &end_sample,
* Python raise it. This results in a much better trace in
* controller.c on the decode() method call.
*/
* Python raise it. This results in a much better trace in
* controller.c on the decode() method call.
*/
}
if (!(l = g_slist_nth(di->pd_output, output_id))) {
srd_err("Protocol decoder %s submitted invalid output ID %d.",
di->decoder->name, output_id);
}
if (!(l = g_slist_nth(di->pd_output, output_id))) {
srd_err("Protocol decoder %s submitted invalid output ID %d.",
di->decoder->name, output_id);
/* An error was already logged. */
break;
}
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
cb->cb(pdata, cb->cb_data);
}
break;
case SRD_OUTPUT_PYTHON:
}
break;
case SRD_OUTPUT_PYTHON:
/* An error was already logged. */
break;
}
/* An error was already logged. */
break;
}
cb->cb(pdata, cb->cb_data);
cb->cb(pdata, cb->cb_data);
}
break;
case SRD_OUTPUT_META:
}
break;
case SRD_OUTPUT_META:
/* An exception was already set up. */
break;
}
/* An exception was already set up. */
break;
}
cb->cb(pdata, cb->cb_data);
cb->cb(pdata, cb->cb_data);
+ PyGILState_Release(gstate);
+
g_free(pdata);
Py_RETURN_NONE;
g_free(pdata);
Py_RETURN_NONE;
+
+err:
+ PyGILState_Release(gstate);
+
+ return NULL;
}
static PyObject *Decoder_register(PyObject *self, PyObject *args,
}
static PyObject *Decoder_register(PyObject *self, PyObject *args,
int output_type;
char *proto_id, *meta_name, *meta_descr;
char *keywords[] = {"output_type", "proto_id", "meta", NULL};
int output_type;
char *proto_id, *meta_name, *meta_descr;
char *keywords[] = {"output_type", "proto_id", "meta", NULL};
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
meta_type_py = NULL;
meta_type_gv = NULL;
meta_type_py = NULL;
meta_type_gv = NULL;
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
}
/* Default to instance id, which defaults to class id. */
}
/* Default to instance id, which defaults to class id. */
&output_type, &proto_id,
&meta_type_py, &meta_name, &meta_descr)) {
/* Let Python raise this exception. */
&output_type, &proto_id,
&meta_type_py, &meta_name, &meta_descr)) {
/* Let Python raise this exception. */
}
/* Check if the meta value's type is supported. */
}
/* Check if the meta value's type is supported. */
meta_type_gv = G_VARIANT_TYPE_DOUBLE;
else {
PyErr_Format(PyExc_TypeError, "Unsupported type.");
meta_type_gv = G_VARIANT_TYPE_DOUBLE;
else {
PyErr_Format(PyExc_TypeError, "Unsupported type.");
di->pd_output = g_slist_append(di->pd_output, pdo);
py_new_output_id = Py_BuildValue("i", pdo->pdo_id);
di->pd_output = g_slist_append(di->pd_output, pdo);
py_new_output_id = Py_BuildValue("i", pdo->pdo_id);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return NULL;
}
static int get_term_type(const char *v)
}
static int get_term_type(const char *v)
const uint8_t *sample_pos;
int byte_offset, bit_offset;
PyObject *py_pinvalues;
const uint8_t *sample_pos;
int byte_offset, bit_offset;
PyObject *py_pinvalues;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!di) {
srd_err("Invalid decoder instance.");
if (!di) {
srd_err("Invalid decoder instance.");
+ PyGILState_Release(gstate);
+ PyGILState_Release(gstate);
+
struct srd_term *term;
uint64_t num_samples_to_skip;
char *term_str;
struct srd_term *term;
uint64_t num_samples_to_skip;
char *term_str;
+ PyGILState_STATE gstate;
if (!py_dict || !term_list)
return SRD_ERR_ARG;
if (!py_dict || !term_list)
return SRD_ERR_ARG;
/* "Create" an empty GSList of terms. */
*term_list = NULL;
/* "Create" an empty GSList of terms. */
*term_list = NULL;
+ gstate = PyGILState_Ensure();
+
/* Iterate over all items in the current dict. */
while (PyDict_Next(py_dict, &pos, &py_key, &py_value)) {
/* Check whether the current key is a string or a number. */
/* Iterate over all items in the current dict. */
while (PyDict_Next(py_dict, &pos, &py_key, &py_value)) {
/* Check whether the current key is a string or a number. */
/* Get the value string. */
if ((py_pydictitem_as_str(py_dict, py_key, &term_str)) != SRD_OK) {
srd_err("Failed to get the value.");
/* Get the value string. */
if ((py_pydictitem_as_str(py_dict, py_key, &term_str)) != SRD_OK) {
srd_err("Failed to get the value.");
}
term = g_malloc0(sizeof(struct srd_term));
term->type = get_term_type(term_str);
}
term = g_malloc0(sizeof(struct srd_term));
term->type = get_term_type(term_str);
/* TODO: Check if it's "skip". */
if ((py_pydictitem_as_long(py_dict, py_key, &num_samples_to_skip)) != SRD_OK) {
srd_err("Failed to get number of samples to skip.");
/* TODO: Check if it's "skip". */
if ((py_pydictitem_as_long(py_dict, py_key, &num_samples_to_skip)) != SRD_OK) {
srd_err("Failed to get number of samples to skip.");
}
term = g_malloc0(sizeof(struct srd_term));
term->type = SRD_TERM_SKIP;
}
term = g_malloc0(sizeof(struct srd_term));
term->type = SRD_TERM_SKIP;
term->num_samples_already_skipped = 0;
} else {
srd_err("Term key is neither a string nor a number.");
term->num_samples_already_skipped = 0;
} else {
srd_err("Term key is neither a string nor a number.");
}
/* Add the term to the list of terms. */
*term_list = g_slist_append(*term_list, term);
}
}
/* Add the term to the list of terms. */
*term_list = g_slist_append(*term_list, term);
}
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR;
GSList *term_list;
PyObject *py_conditionlist, *py_conds, *py_dict;
int i, num_conditions, ret;
GSList *term_list;
PyObject *py_conditionlist, *py_conds, *py_dict;
int i, num_conditions, ret;
+ PyGILState_STATE gstate;
if (!self || !args)
return SRD_ERR_ARG;
if (!self || !args)
return SRD_ERR_ARG;
+ gstate = PyGILState_Ensure();
+
/* Get the decoder instance. */
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
/* Get the decoder instance. */
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
*/
if (di->want_wait_terminate) {
srd_dbg("%s: %s: Skip (want_term).", di->inst_id, __func__);
*/
if (di->want_wait_terminate) {
srd_dbg("%s: %s: Skip (want_term).", di->inst_id, __func__);
py_conds = Py_None;
if (!PyArg_ParseTuple(args, "|O", &py_conds)) {
/* Let Python raise this exception. */
py_conds = Py_None;
if (!PyArg_ParseTuple(args, "|O", &py_conds)) {
/* Let Python raise this exception. */
}
if (py_conds == Py_None) {
/* 'py_conds' is None. */
}
if (py_conds == Py_None) {
/* 'py_conds' is None. */
} else if (PyList_Check(py_conds)) {
/* 'py_conds' is a list. */
py_conditionlist = py_conds;
num_conditions = PyList_Size(py_conditionlist);
if (num_conditions == 0)
} else if (PyList_Check(py_conds)) {
/* 'py_conds' is a list. */
py_conditionlist = py_conds;
num_conditions = PyList_Size(py_conditionlist);
if (num_conditions == 0)
- return 9999; /* The PD invoked self.wait([]). */
+ goto ret_9999; /* The PD invoked self.wait([]). */
Py_IncRef(py_conditionlist);
} else if (PyDict_Check(py_conds)) {
/* 'py_conds' is a dict. */
if (PyDict_Size(py_conds) == 0)
Py_IncRef(py_conditionlist);
} else if (PyDict_Check(py_conds)) {
/* 'py_conds' is a dict. */
if (PyDict_Size(py_conds) == 0)
- return 9999; /* The PD invoked self.wait({}). */
+ goto ret_9999; /* The PD invoked self.wait({}). */
/* Make a list and put the dict in there for convenience. */
py_conditionlist = PyList_New(1);
Py_IncRef(py_conds);
/* Make a list and put the dict in there for convenience. */
py_conditionlist = PyList_New(1);
Py_IncRef(py_conds);
num_conditions = 1;
} else {
srd_err("Condition list is neither a list nor a dict.");
num_conditions = 1;
} else {
srd_err("Condition list is neither a list nor a dict.");
}
/* Free the old condition list. */
}
/* Free the old condition list. */
Py_DecRef(py_conditionlist);
Py_DecRef(py_conditionlist);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR;
+
+ret_9999:
+ PyGILState_Release(gstate);
+
+ return 9999;
gboolean found_match;
struct srd_decoder_inst *di;
PyObject *py_pinvalues, *py_matched;
gboolean found_match;
struct srd_decoder_inst *di;
PyObject *py_pinvalues, *py_matched;
+ PyGILState_STATE gstate;
if (!self || !args)
return NULL;
if (!self || !args)
return NULL;
+ gstate = PyGILState_Ensure();
+
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
+ PyGILState_Release(gstate);
Py_RETURN_NONE;
}
ret = set_new_condition_list(self, args);
if (ret < 0) {
srd_dbg("%s: %s: Aborting wait().", di->inst_id, __func__);
Py_RETURN_NONE;
}
ret = set_new_condition_list(self, args);
if (ret < 0) {
srd_dbg("%s: %s: Aborting wait().", di->inst_id, __func__);
if (ret < 0) {
srd_dbg("%s: %s: Cannot setup condition-less wait().",
di->inst_id, __func__);
if (ret < 0) {
srd_dbg("%s: %s: Cannot setup condition-less wait().",
di->inst_id, __func__);
+
+ Py_BEGIN_ALLOW_THREADS
+
/* Wait for new samples to process, or termination request. */
g_mutex_lock(&di->data_mutex);
while (!di->got_new_samples && !di->want_wait_terminate)
/* Wait for new samples to process, or termination request. */
g_mutex_lock(&di->data_mutex);
while (!di->got_new_samples && !di->want_wait_terminate)
found_match = FALSE;
ret = process_samples_until_condition_match(di, &found_match);
found_match = FALSE;
ret = process_samples_until_condition_match(di, &found_match);
/* If there's a match, set self.samplenum etc. and return. */
if (found_match) {
/* Set self.samplenum to the (absolute) sample number that matched. */
/* If there's a match, set self.samplenum etc. and return. */
if (found_match) {
/* Set self.samplenum to the (absolute) sample number that matched. */
g_mutex_unlock(&di->data_mutex);
g_mutex_unlock(&di->data_mutex);
+ PyGILState_Release(gstate);
+
srd_dbg("%s: %s: Will return from wait().",
di->inst_id, __func__);
g_mutex_unlock(&di->data_mutex);
srd_dbg("%s: %s: Will return from wait().",
di->inst_id, __func__);
g_mutex_unlock(&di->data_mutex);
}
g_mutex_unlock(&di->data_mutex);
}
}
g_mutex_unlock(&di->data_mutex);
}
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return NULL;
int idx, max_idx;
struct srd_decoder_inst *di;
PyObject *py_channel;
int idx, max_idx;
struct srd_decoder_inst *di;
PyObject *py_channel;
+ PyGILState_STATE gstate;
if (!self || !args)
return NULL;
if (!self || !args)
return NULL;
+ gstate = PyGILState_Ensure();
+
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
if (!(di = srd_inst_find_by_obj(NULL, self))) {
PyErr_SetString(PyExc_Exception, "decoder instance not found");
}
/* Parse the argument of self.has_channel() into 'py_channel'. */
if (!PyArg_ParseTuple(args, "O", &py_channel)) {
/* Let Python raise this exception. */
}
/* Parse the argument of self.has_channel() into 'py_channel'. */
if (!PyArg_ParseTuple(args, "O", &py_channel)) {
/* Let Python raise this exception. */
}
if (!PyLong_Check(py_channel)) {
PyErr_SetString(PyExc_Exception, "channel index not a number");
}
if (!PyLong_Check(py_channel)) {
PyErr_SetString(PyExc_Exception, "channel index not a number");
}
idx = PyLong_AsLong(py_channel);
}
idx = PyLong_AsLong(py_channel);
if (idx < 0 || idx > max_idx) {
srd_err("Invalid channel index %d/%d.", idx, max_idx);
PyErr_SetString(PyExc_Exception, "invalid channel");
if (idx < 0 || idx > max_idx) {
srd_err("Invalid channel index %d/%d.", idx, max_idx);
PyErr_SetString(PyExc_Exception, "invalid channel");
+ PyGILState_Release(gstate);
+
return (di->dec_channelmap[idx] == -1) ? Py_False : Py_True;
return (di->dec_channelmap[idx] == -1) ? Py_False : Py_True;
+
+err:
+ PyGILState_Release(gstate);
+
+ return NULL;
}
static PyMethodDef Decoder_methods[] = {
}
static PyMethodDef Decoder_methods[] = {
{ Py_tp_new, (void *)&PyType_GenericNew },
{ 0, NULL }
};
{ Py_tp_new, (void *)&PyType_GenericNew },
{ 0, NULL }
};
+ PyObject *py_obj;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
+
spec.name = "sigrokdecode.Decoder";
spec.basicsize = sizeof(srd_Decoder);
spec.itemsize = 0;
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
spec.slots = slots;
spec.name = "sigrokdecode.Decoder";
spec.basicsize = sizeof(srd_Decoder);
spec.itemsize = 0;
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
spec.slots = slots;
- return PyType_FromSpec(&spec);
+ py_obj = PyType_FromSpec(&spec);
+
+ PyGILState_Release(gstate);
+
+ return py_obj;
SRD_PRIV PyObject *py_import_by_name(const char *name)
{
PyObject *py_mod, *py_modname;
SRD_PRIV PyObject *py_import_by_name(const char *name)
{
PyObject *py_mod, *py_modname;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
py_modname = PyUnicode_FromString(name);
py_modname = PyUnicode_FromString(name);
+ if (!py_modname) {
+ PyGILState_Release(gstate);
py_mod = PyImport_Import(py_modname);
Py_DECREF(py_modname);
py_mod = PyImport_Import(py_modname);
Py_DECREF(py_modname);
+ PyGILState_Release(gstate);
+
{
PyObject *py_str;
int ret;
{
PyObject *py_str;
int ret;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!PyObject_HasAttrString(py_obj, attr)) {
srd_dbg("Object has no attribute '%s'.", attr);
if (!PyObject_HasAttrString(py_obj, attr)) {
srd_dbg("Object has no attribute '%s'.", attr);
}
if (!(py_str = PyObject_GetAttrString(py_obj, attr))) {
srd_exception_catch("Failed to get attribute '%s'", attr);
}
if (!(py_str = PyObject_GetAttrString(py_obj, attr))) {
srd_exception_catch("Failed to get attribute '%s'", attr);
}
ret = py_str_as_str(py_str, outstr);
Py_DECREF(py_str);
}
ret = py_str_as_str(py_str, outstr);
Py_DECREF(py_str);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
Py_ssize_t i;
int ret;
char *outstr;
Py_ssize_t i;
int ret;
char *outstr;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!PyObject_HasAttrString(py_obj, attr)) {
srd_dbg("Object has no attribute '%s'.", attr);
if (!PyObject_HasAttrString(py_obj, attr)) {
srd_dbg("Object has no attribute '%s'.", attr);
}
if (!(py_list = PyObject_GetAttrString(py_obj, attr))) {
srd_exception_catch("Failed to get attribute '%s'", attr);
}
if (!(py_list = PyObject_GetAttrString(py_obj, attr))) {
srd_exception_catch("Failed to get attribute '%s'", attr);
}
if (!PyList_Check(py_list)) {
srd_dbg("Object is not a list.");
}
if (!PyList_Check(py_list)) {
srd_dbg("Object is not a list.");
ret = py_listitem_as_str(py_list, i, &outstr);
if (ret < 0) {
srd_dbg("Couldn't get item %" PY_FORMAT_SIZE_T "d.", i);
ret = py_listitem_as_str(py_list, i, &outstr);
if (ret < 0) {
srd_dbg("Couldn't get item %" PY_FORMAT_SIZE_T "d.", i);
}
*outstrlist = g_slist_append(*outstrlist, outstr);
}
Py_DECREF(py_list);
}
*outstrlist = g_slist_append(*outstrlist, outstr);
}
Py_DECREF(py_list);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
char **outstr)
{
PyObject *py_value;
char **outstr)
{
PyObject *py_value;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
}
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
srd_dbg("Dictionary has no attribute '%s'.", key);
}
if (!(py_value = PyDict_GetItemString(py_obj, key))) {
srd_dbg("Dictionary has no attribute '%s'.", key);
+ PyGILState_Release(gstate);
+
return py_str_as_str(py_value, outstr);
return py_str_as_str(py_value, outstr);
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
char **outstr)
{
PyObject *py_value;
char **outstr)
{
PyObject *py_value;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!PyList_Check(py_obj)) {
srd_dbg("Object is not a list.");
if (!PyList_Check(py_obj)) {
srd_dbg("Object is not a list.");
}
if (!(py_value = PyList_GetItem(py_obj, idx))) {
srd_dbg("Couldn't get list item %" PY_FORMAT_SIZE_T "d.", idx);
}
if (!(py_value = PyList_GetItem(py_obj, idx))) {
srd_dbg("Couldn't get list item %" PY_FORMAT_SIZE_T "d.", idx);
+ PyGILState_Release(gstate);
+
return py_str_as_str(py_value, outstr);
return py_str_as_str(py_value, outstr);
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
char **outstr)
{
PyObject *py_value;
char **outstr)
{
PyObject *py_value;
+ PyGILState_STATE gstate;
if (!py_obj || !py_key || !outstr)
return SRD_ERR_ARG;
if (!py_obj || !py_key || !outstr)
return SRD_ERR_ARG;
+ gstate = PyGILState_Ensure();
+
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
}
if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
srd_dbg("Dictionary has no such key.");
}
if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
srd_dbg("Dictionary has no such key.");
}
if (!PyUnicode_Check(py_value)) {
srd_dbg("Dictionary value should be a string.");
}
if (!PyUnicode_Check(py_value)) {
srd_dbg("Dictionary value should be a string.");
}
return py_str_as_str(py_value, outstr);
}
return py_str_as_str(py_value, outstr);
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
SRD_PRIV int py_pydictitem_as_long(PyObject *py_obj, PyObject *py_key, uint64_t *out)
{
PyObject *py_value;
SRD_PRIV int py_pydictitem_as_long(PyObject *py_obj, PyObject *py_key, uint64_t *out)
{
PyObject *py_value;
+ PyGILState_STATE gstate;
if (!py_obj || !py_key || !out)
return SRD_ERR_ARG;
if (!py_obj || !py_key || !out)
return SRD_ERR_ARG;
+ gstate = PyGILState_Ensure();
+
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
if (!PyDict_Check(py_obj)) {
srd_dbg("Object is not a dictionary.");
}
if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
srd_dbg("Dictionary has no such key.");
}
if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
srd_dbg("Dictionary has no such key.");
}
if (!PyLong_Check(py_value)) {
srd_dbg("Dictionary value should be a long.");
}
if (!PyLong_Check(py_value)) {
srd_dbg("Dictionary value should be a long.");
}
*out = PyLong_AsUnsignedLongLong(py_value);
}
*out = PyLong_AsUnsignedLongLong(py_value);
+ PyGILState_Release(gstate);
+
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR_PYTHON;
{
PyObject *py_bytes;
char *str;
{
PyObject *py_bytes;
char *str;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (!PyUnicode_Check(py_str)) {
srd_dbg("Object is not a string object.");
if (!PyUnicode_Check(py_str)) {
srd_dbg("Object is not a string object.");
+ PyGILState_Release(gstate);
Py_DECREF(py_bytes);
if (str) {
*outstr = str;
Py_DECREF(py_bytes);
if (str) {
*outstr = str;
+ PyGILState_Release(gstate);
return SRD_OK;
}
}
srd_exception_catch("Failed to extract string");
return SRD_OK;
}
}
srd_exception_catch("Failed to extract string");
+ PyGILState_Release(gstate);
+
PyObject *py_item, *py_bytes;
char **strv, *str;
ssize_t seq_len, i;
PyObject *py_item, *py_bytes;
char **strv, *str;
ssize_t seq_len, i;
+ PyGILState_STATE gstate;
+ int ret = SRD_ERR_PYTHON;
+
+ gstate = PyGILState_Ensure();
if (!PySequence_Check(py_strseq)) {
srd_err("Object does not provide sequence protocol.");
if (!PySequence_Check(py_strseq)) {
srd_err("Object does not provide sequence protocol.");
}
seq_len = PySequence_Size(py_strseq);
if (seq_len < 0) {
srd_exception_catch("Failed to obtain sequence size");
}
seq_len = PySequence_Size(py_strseq);
if (seq_len < 0) {
srd_exception_catch("Failed to obtain sequence size");
}
strv = g_try_new0(char *, seq_len + 1);
if (!strv) {
srd_err("Failed to allocate result string vector.");
}
strv = g_try_new0(char *, seq_len + 1);
if (!strv) {
srd_err("Failed to allocate result string vector.");
+ ret = SRD_ERR_MALLOC;
+ goto err;
}
for (i = 0; i < seq_len; i++) {
}
for (i = 0; i < seq_len; i++) {
g_strfreev(strv);
srd_exception_catch("Failed to obtain string item");
g_strfreev(strv);
srd_exception_catch("Failed to obtain string item");
+err:
+ PyGILState_Release(gstate);
+
+ return ret;
SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
{
GVariant *var = NULL;
SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
{
GVariant *var = NULL;
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
if (PyUnicode_Check(py_obj)) { /* string */
PyObject *py_bytes;
if (PyUnicode_Check(py_obj)) { /* string */
PyObject *py_bytes;
srd_err("Failed to extract value of unsupported type.");
}
srd_err("Failed to extract value of unsupported type.");
}
+ PyGILState_Release(gstate);
+