diff options
-rw-r--r-- | decoder.c | 86 | ||||
-rw-r--r-- | exception.c | 9 | ||||
-rw-r--r-- | instance.c | 30 | ||||
-rw-r--r-- | module_sigrokdecode.c | 6 | ||||
-rw-r--r-- | session.c | 5 | ||||
-rw-r--r-- | srd.c | 30 | ||||
-rw-r--r-- | type_decoder.c | 207 | ||||
-rw-r--r-- | util.c | 127 |
8 files changed, 427 insertions, 73 deletions
@@ -152,11 +152,15 @@ static void decoder_option_free(void *data) static void decoder_free(struct srd_decoder *dec) { + PyGILState_STATE gstate; + if (!dec) return; + gstate = PyGILState_Ensure(); 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); @@ -183,10 +187,15 @@ static int get_channels(const struct srd_decoder *d, const char *attr, 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. */ + PyGILState_Release(gstate); return SRD_OK; + } pdchl = NULL; @@ -227,6 +236,8 @@ static int get_channels(const struct srd_decoder *d, const char *attr, Py_DECREF(py_channellist); *out_pdchl = pdchl; + PyGILState_Release(gstate); + return SRD_OK; except_out: @@ -235,6 +246,7 @@ except_out: err_out: g_slist_free_full(pdchl, &channel_free); Py_XDECREF(py_channellist); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -246,10 +258,15 @@ static int get_options(struct srd_decoder *d) 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. */ + PyGILState_Release(gstate); return SRD_OK; + } options = NULL; @@ -342,6 +359,7 @@ static int get_options(struct srd_decoder *d) } d->options = options; Py_DECREF(py_opts); + PyGILState_Release(gstate); return SRD_OK; @@ -350,6 +368,7 @@ except_out: err_out: g_slist_free_full(options, &decoder_option_free); Py_XDECREF(py_opts); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -362,9 +381,14 @@ static int get_annotations(struct srd_decoder *dec) 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); return SRD_OK; + } annotations = NULL; @@ -396,6 +420,7 @@ static int get_annotations(struct srd_decoder *dec) } dec->annotations = annotations; Py_DECREF(py_annlist); + PyGILState_Release(gstate); return SRD_OK; @@ -404,6 +429,7 @@ except_out: err_out: g_slist_free_full(annotations, (GDestroyNotify)&g_strfreev); Py_XDECREF(py_annlist); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -417,9 +443,14 @@ static int get_annotation_rows(struct srd_decoder *dec) 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); return SRD_OK; + } annotation_rows = NULL; @@ -492,6 +523,7 @@ static int get_annotation_rows(struct srd_decoder *dec) } dec->annotation_rows = annotation_rows; Py_DECREF(py_ann_rows); + PyGILState_Release(gstate); return SRD_OK; @@ -501,6 +533,7 @@ except_out: err_out: g_slist_free_full(annotation_rows, &annotation_row_free); Py_XDECREF(py_ann_rows); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -513,9 +546,14 @@ static int get_binary_classes(struct srd_decoder *dec) 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); return SRD_OK; + } bin_classes = NULL; @@ -548,6 +586,7 @@ static int get_binary_classes(struct srd_decoder *dec) } dec->binary = bin_classes; Py_DECREF(py_bin_classes); + PyGILState_Release(gstate); return SRD_OK; @@ -557,6 +596,7 @@ except_out: err_out: g_slist_free_full(bin_classes, (GDestroyNotify)&g_strfreev); Py_XDECREF(py_bin_classes); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -568,17 +608,23 @@ static int check_method(PyObject *py_dec, const char *mod_name, { 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); + PyGILState_Release(gstate); 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); @@ -601,15 +647,20 @@ SRD_PRIV long srd_decoder_apiver(const struct srd_decoder *d) { PyObject *py_apiver; long apiver; + PyGILState_STATE gstate; if (!d) return 0; + 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); + PyGILState_Release(gstate); + return apiver; } @@ -629,6 +680,7 @@ SRD_API int srd_decoder_load(const char *module_name) long apiver; int is_subclass; const char *fail_txt; + PyGILState_STATE gstate; if (!srd_check_init()) return SRD_ERR; @@ -636,8 +688,11 @@ SRD_API int srd_decoder_load(const char *module_name) if (!module_name) return SRD_ERR_ARG; + gstate = PyGILState_Ensure(); + if (PyDict_GetItemString(PyImport_GetModuleDict(), module_name)) { /* Module was already imported. */ + PyGILState_Release(gstate); return SRD_OK; } @@ -775,6 +830,8 @@ SRD_API int srd_decoder_load(const char *module_name) goto err_out; } + PyGILState_Release(gstate); + /* Append it to the list of loaded decoders. */ pd_list = g_slist_append(pd_list, d); @@ -791,6 +848,7 @@ err_out: if (fail_txt) srd_err("Failed to load decoder %s: %s", module_name, fail_txt); decoder_free(d); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -809,6 +867,7 @@ SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec) { PyObject *py_str; char *doc; + PyGILState_STATE gstate; if (!srd_check_init()) return NULL; @@ -816,12 +875,14 @@ SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec) if (!dec) return NULL; + gstate = PyGILState_Ensure(); + if (!PyObject_HasAttrString(dec->py_mod, "__doc__")) - return NULL; + goto err; if (!(py_str = PyObject_GetAttrString(dec->py_mod, "__doc__"))) { srd_exception_catch("Failed to get docstring"); - return NULL; + goto err; } doc = NULL; @@ -829,7 +890,14 @@ SRD_API char *srd_decoder_doc_get(const struct srd_decoder *dec) py_str_as_str(py_str, &doc); Py_DECREF(py_str); + PyGILState_Release(gstate); + return doc; + +err: + PyGILState_Release(gstate); + + return NULL; } /** @@ -880,9 +948,12 @@ static void srd_decoder_load_all_zip_path(char *path) Py_ssize_t pos = 0; char *prefix; size_t prefix_len; + PyGILState_STATE gstate; 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; @@ -951,6 +1022,7 @@ err_out: Py_XDECREF(zipimporter_class); Py_XDECREF(zipimport_mod); PyErr_Clear(); + PyGILState_Release(gstate); } static void srd_decoder_load_all_path(char *path) 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); } @@ -73,6 +73,7 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, gint64 val_int; int ret; const char *val_str; + PyGILState_STATE gstate; if (!di) { srd_err("Invalid decoder instance."); @@ -84,8 +85,11 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di, return SRD_ERR_ARG; } + gstate = PyGILState_Ensure(); + 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; @@ -167,6 +171,7 @@ err_out: srd_exception_catch("Stray exception in srd_inst_option_set()"); ret = SRD_ERR_PYTHON; } + PyGILState_Release(gstate); return ret; } @@ -297,6 +302,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, 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); @@ -357,16 +363,21 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, 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); + PyGILState_Release(gstate); 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); @@ -477,7 +488,6 @@ SRD_API int srd_inst_stack(struct srd_session *sess, 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; @@ -694,14 +704,18 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di) 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); + 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); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } Py_DecRef(py_res); @@ -712,6 +726,8 @@ SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di) /* 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; @@ -1033,6 +1049,7 @@ static gpointer di_thread(gpointer data) PyObject *py_res; struct srd_decoder_inst *di; int wanted_term; + PyGILState_STATE gstate; if (!data) return NULL; @@ -1041,6 +1058,8 @@ static gpointer di_thread(gpointer data) 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. @@ -1076,6 +1095,7 @@ static gpointer di_thread(gpointer data) */ srd_dbg("%s: Thread done (!res, want_term).", di->inst_id); PyErr_Clear(); + PyGILState_Release(gstate); return NULL; } if (!py_res) { @@ -1087,6 +1107,7 @@ static gpointer di_thread(gpointer data) 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); return NULL; } @@ -1099,6 +1120,8 @@ static gpointer di_thread(gpointer data) Py_DecRef(py_res); PyErr_Clear(); + PyGILState_Release(gstate); + srd_dbg("%s: Thread done (with res).", di->inst_id); return NULL; @@ -1228,13 +1251,18 @@ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di) { 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_inst_reset_state(di); + gstate = PyGILState_Ensure(); Py_DecRef(di->py_inst); + PyGILState_Release(gstate); + g_free(di->inst_id); g_free(di->dec_channelmap); g_free(di->channel_samples); diff --git a/module_sigrokdecode.c b/module_sigrokdecode.c index a0d9610..ab5df19 100644 --- a/module_sigrokdecode.c +++ b/module_sigrokdecode.c @@ -42,6 +42,9 @@ static struct PyModuleDef sigrokdecode_module = { PyMODINIT_FUNC PyInit_sigrokdecode(void) { PyObject *mod, *Decoder_type; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); mod = PyModule_Create(&sigrokdecode_module); if (!mod) @@ -68,10 +71,13 @@ PyMODINIT_FUNC PyInit_sigrokdecode(void) mod_sigrokdecode = mod; + PyGILState_Release(gstate); + return mod; err_out: Py_XDECREF(mod); srd_exception_catch("Failed to initialize module"); + PyGILState_Release(gstate); return NULL; } @@ -131,11 +131,14 @@ static int srd_inst_send_meta(struct srd_decoder_inst *di, int key, 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; + gstate = PyGILState_Ensure(); + if (PyObject_HasAttrString(di->py_inst, "metadata")) { py_ret = PyObject_CallMethod(di->py_inst, "metadata", "lK", (long)SRD_CONF_SAMPLERATE, @@ -143,6 +146,8 @@ static int srd_inst_send_meta(struct srd_decoder_inst *di, int key, Py_XDECREF(py_ret); } + 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; @@ -232,6 +232,12 @@ SRD_API int srd_init(const char *path) } } + /* 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; @@ -261,9 +267,17 @@ SRD_API int srd_exit(void) 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(); + /* Note: No need to release the GIL since Python is shut down now. */ + max_session_id = -1; return SRD_OK; @@ -291,28 +305,38 @@ SRD_API int srd_exit(void) 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); + gstate = PyGILState_Ensure(); + py_cur_path = PySys_GetObject("path"); if (!py_cur_path) - return SRD_ERR_PYTHON; + goto err; py_item = PyUnicode_FromString(path); if (!py_item) { srd_exception_catch("Failed to create Unicode object"); - return SRD_ERR_PYTHON; + goto err; } if (PyList_Insert(py_cur_path, 0, py_item) < 0) { srd_exception_catch("Failed to insert path element"); Py_DECREF(py_item); - return SRD_ERR_PYTHON; + goto err; } Py_DECREF(py_item); + PyGILState_Release(gstate); + searchpaths = g_slist_prepend(searchpaths, g_strdup(path)); return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @} */ diff --git a/type_decoder.c b/type_decoder.c index 231a893..f203377 100644 --- a/type_decoder.c +++ b/type_decoder.c @@ -48,12 +48,15 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, 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); - return SRD_ERR_PYTHON; + goto err; } /* Should have 2 elements. */ @@ -61,7 +64,7 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, srd_err("Protocol decoder %s submitted annotation list with " "%zd elements instead of 2", di->decoder->name, PyList_Size(obj)); - return SRD_ERR_PYTHON; + goto err; } /* @@ -72,13 +75,13 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, if (!PyLong_Check(py_tmp)) { srd_err("Protocol decoder %s submitted annotation list, but " "first element was not an integer.", di->decoder->name); - return SRD_ERR_PYTHON; + goto err; } 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); - return SRD_ERR_PYTHON; + goto err; } /* Second element must be a list. */ @@ -86,12 +89,12 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, if (!PyList_Check(py_tmp)) { srd_err("Protocol decoder %s submitted annotation list, but " "second element was not a list.", di->decoder->name); - return SRD_ERR_PYTHON; + goto err; } 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); - return SRD_ERR_PYTHON; + goto err; } pda = g_malloc(sizeof(struct srd_proto_data_annotation)); @@ -99,7 +102,14 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, pda->ann_text = ann_text; pdata->data = pda; + PyGILState_Release(gstate); + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, @@ -110,12 +120,15 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, 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); - return SRD_ERR_PYTHON; + goto err; } /* Should have 2 elements. */ @@ -123,7 +136,7 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list " "with %zd elements instead of 2", di->decoder->name, PyList_Size(obj)); - return SRD_ERR_PYTHON; + goto err; } /* The first element should be an integer. */ @@ -131,13 +144,13 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, 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); - return SRD_ERR_PYTHON; + goto err; } 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); - return SRD_ERR_PYTHON; + goto err; } /* Second element should be bytes. */ @@ -145,19 +158,22 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, if (!PyBytes_Check(py_tmp)) { srd_err("Protocol decoder %s submitted SRD_OUTPUT_BINARY list, " "but second element was not bytes.", di->decoder->name); - return SRD_ERR_PYTHON; + goto err; } /* 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); - return SRD_ERR_PYTHON; + goto err; } pdb = g_malloc(sizeof(struct srd_proto_data_binary)); if (PyBytes_AsStringAndSize(py_tmp, &buf, &size) == -1) - return SRD_ERR_PYTHON; + goto err; + + PyGILState_Release(gstate); + pdb->bin_class = bin_class; pdb->size = size; if (!(pdb->data = g_try_malloc(pdb->size))) @@ -166,36 +182,51 @@ static int convert_binary(struct srd_decoder_inst *di, PyObject *obj, 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; + 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."); - return SRD_ERR_PYTHON; + goto err; } intvalue = PyLong_AsLongLong(obj); if (PyErr_Occurred()) - return SRD_ERR_PYTHON; + goto err; 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."); - return SRD_ERR_PYTHON; + goto err; } dvalue = PyFloat_AsDouble(obj); if (PyErr_Occurred()) - return SRD_ERR_PYTHON; + goto err; pdata->data = g_variant_new_double(dvalue); } + PyGILState_Release(gstate); + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } static PyObject *Decoder_put(PyObject *self, PyObject *args) @@ -208,11 +239,14 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) 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."); - return NULL; + goto err; } if (!PyArg_ParseTuple(args, "KKiO", &start_sample, &end_sample, @@ -222,13 +256,13 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) * Python raise it. This results in a much better trace in * controller.c on the decode() method call. */ - return NULL; + goto err; } 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); - return NULL; + goto err; } pdo = l->data; @@ -250,7 +284,9 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) /* An error was already logged. */ break; } + Py_BEGIN_ALLOW_THREADS cb->cb(pdata, cb->cb_data); + Py_END_ALLOW_THREADS } break; case SRD_OUTPUT_PYTHON: @@ -280,7 +316,9 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) /* An error was already logged. */ break; } + Py_BEGIN_ALLOW_THREADS cb->cb(pdata, cb->cb_data); + Py_END_ALLOW_THREADS } break; case SRD_OUTPUT_META: @@ -290,7 +328,9 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) /* An exception was already set up. */ break; } + Py_BEGIN_ALLOW_THREADS cb->cb(pdata, cb->cb_data); + Py_END_ALLOW_THREADS } break; default: @@ -299,9 +339,16 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) break; } + PyGILState_Release(gstate); + g_free(pdata); Py_RETURN_NONE; + +err: + PyGILState_Release(gstate); + + return NULL; } static PyObject *Decoder_register(PyObject *self, PyObject *args, @@ -315,6 +362,9 @@ 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}; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); meta_type_py = NULL; meta_type_gv = NULL; @@ -322,7 +372,7 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); - return NULL; + goto err; } /* Default to instance id, which defaults to class id. */ @@ -331,7 +381,7 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, &output_type, &proto_id, &meta_type_py, &meta_name, &meta_descr)) { /* Let Python raise this exception. */ - return NULL; + goto err; } /* Check if the meta value's type is supported. */ @@ -342,7 +392,7 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, meta_type_gv = G_VARIANT_TYPE_DOUBLE; else { PyErr_Format(PyExc_TypeError, "Unsupported type."); - return NULL; + goto err; } } @@ -366,7 +416,14 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, di->pd_output = g_slist_append(di->pd_output, pdo); py_new_output_id = Py_BuildValue("i", pdo->pdo_id); + PyGILState_Release(gstate); + return py_new_output_id; + +err: + PyGILState_Release(gstate); + + return NULL; } static int get_term_type(const char *v) @@ -405,9 +462,13 @@ static PyObject *get_current_pinvalues(const struct srd_decoder_inst *di) 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."); + PyGILState_Release(gstate); return NULL; } @@ -427,6 +488,8 @@ static PyObject *get_current_pinvalues(const struct srd_decoder_inst *di) } } + PyGILState_Release(gstate); + return py_pinvalues; } @@ -448,6 +511,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list) 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; @@ -455,6 +519,8 @@ static int create_term_list(PyObject *py_dict, GSList **term_list) /* "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. */ @@ -464,7 +530,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list) /* Get the value string. */ if ((py_pydictitem_as_str(py_dict, py_key, &term_str)) != SRD_OK) { srd_err("Failed to get the value."); - return SRD_ERR; + goto err; } term = g_malloc0(sizeof(struct srd_term)); term->type = get_term_type(term_str); @@ -475,7 +541,7 @@ static int create_term_list(PyObject *py_dict, GSList **term_list) /* 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."); - return SRD_ERR; + goto err; } term = g_malloc0(sizeof(struct srd_term)); term->type = SRD_TERM_SKIP; @@ -483,14 +549,21 @@ static int create_term_list(PyObject *py_dict, GSList **term_list) term->num_samples_already_skipped = 0; } else { srd_err("Term key is neither a string nor a number."); - return SRD_ERR; + goto err; } /* Add the term to the list of terms. */ *term_list = g_slist_append(*term_list, term); } + PyGILState_Release(gstate); + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR; } /** @@ -510,14 +583,17 @@ static int set_new_condition_list(PyObject *self, PyObject *args) 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; + gstate = PyGILState_Ensure(); + /* Get the decoder instance. */ if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); - return SRD_ERR; + goto err; } /* @@ -526,7 +602,7 @@ static int set_new_condition_list(PyObject *self, PyObject *args) */ if (di->want_wait_terminate) { srd_dbg("%s: %s: Skip (want_term).", di->inst_id, __func__); - return SRD_ERR; + goto err; } /* @@ -539,22 +615,22 @@ static int set_new_condition_list(PyObject *self, PyObject *args) py_conds = Py_None; if (!PyArg_ParseTuple(args, "|O", &py_conds)) { /* Let Python raise this exception. */ - return SRD_ERR; + goto err; } if (py_conds == Py_None) { /* 'py_conds' is None. */ - return 9999; + goto ret_9999; } 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) - 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); @@ -562,7 +638,7 @@ static int set_new_condition_list(PyObject *self, PyObject *args) num_conditions = 1; } else { srd_err("Condition list is neither a list nor a dict."); - return SRD_ERR; + goto err; } /* Free the old condition list. */ @@ -590,7 +666,19 @@ static int set_new_condition_list(PyObject *self, PyObject *args) Py_DecRef(py_conditionlist); + PyGILState_Release(gstate); + return ret; + +err: + PyGILState_Release(gstate); + + return SRD_ERR; + +ret_9999: + PyGILState_Release(gstate); + + return 9999; } /** @@ -636,19 +724,23 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) gboolean found_match; struct srd_decoder_inst *di; PyObject *py_pinvalues, *py_matched; + PyGILState_STATE gstate; 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"); + 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__); - return NULL; + goto err; } if (ret == 9999) { /* @@ -668,11 +760,14 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) if (ret < 0) { srd_dbg("%s: %s: Cannot setup condition-less wait().", di->inst_id, __func__); - return NULL; + goto err; } } while (1) { + + 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) @@ -688,6 +783,8 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) found_match = FALSE; ret = process_samples_until_condition_match(di, &found_match); + Py_END_ALLOW_THREADS + /* If there's a match, set self.samplenum etc. and return. */ if (found_match) { /* Set self.samplenum to the (absolute) sample number that matched. */ @@ -708,6 +805,8 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) g_mutex_unlock(&di->data_mutex); + PyGILState_Release(gstate); + return py_pinvalues; } @@ -730,13 +829,20 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) srd_dbg("%s: %s: Will return from wait().", di->inst_id, __func__); g_mutex_unlock(&di->data_mutex); - return NULL; + goto err; } g_mutex_unlock(&di->data_mutex); } + PyGILState_Release(gstate); + Py_RETURN_NONE; + +err: + PyGILState_Release(gstate); + + return NULL; } /** @@ -754,24 +860,27 @@ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args) int idx, max_idx; struct srd_decoder_inst *di; PyObject *py_channel; + PyGILState_STATE gstate; 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"); - return NULL; + goto err; } /* Parse the argument of self.has_channel() into 'py_channel'. */ if (!PyArg_ParseTuple(args, "O", &py_channel)) { /* Let Python raise this exception. */ - return NULL; + goto err; } if (!PyLong_Check(py_channel)) { PyErr_SetString(PyExc_Exception, "channel index not a number"); - return NULL; + goto err; } idx = PyLong_AsLong(py_channel); @@ -781,10 +890,17 @@ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args) if (idx < 0 || idx > max_idx) { srd_err("Invalid channel index %d/%d.", idx, max_idx); PyErr_SetString(PyExc_Exception, "invalid channel"); - return NULL; + goto err; } + PyGILState_Release(gstate); + return (di->dec_channelmap[idx] == -1) ? Py_False : Py_True; + +err: + PyGILState_Release(gstate); + + return NULL; } static PyMethodDef Decoder_methods[] = { @@ -815,11 +931,20 @@ SRD_PRIV PyObject *srd_Decoder_type_new(void) { 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; - return PyType_FromSpec(&spec); + py_obj = PyType_FromSpec(&spec); + + PyGILState_Release(gstate); + + return py_obj; } @@ -36,14 +36,21 @@ 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); - if (!py_modname) + if (!py_modname) { + PyGILState_Release(gstate); return NULL; + } py_mod = PyImport_Import(py_modname); Py_DECREF(py_modname); + PyGILState_Release(gstate); + return py_mod; } @@ -64,21 +71,31 @@ SRD_PRIV int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr) { 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); - return SRD_ERR_PYTHON; + goto err; } if (!(py_str = PyObject_GetAttrString(py_obj, attr))) { srd_exception_catch("Failed to get attribute '%s'", attr); - return SRD_ERR_PYTHON; + goto err; } ret = py_str_as_str(py_str, outstr); Py_DECREF(py_str); + PyGILState_Release(gstate); + return ret; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -101,20 +118,23 @@ SRD_PRIV int py_attr_as_strlist(PyObject *py_obj, const char *attr, GSList **out 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); - return SRD_ERR_PYTHON; + goto err; } if (!(py_list = PyObject_GetAttrString(py_obj, attr))) { srd_exception_catch("Failed to get attribute '%s'", attr); - return SRD_ERR_PYTHON; + goto err; } if (!PyList_Check(py_list)) { srd_dbg("Object is not a list."); - return SRD_ERR_PYTHON; + goto err; } *outstrlist = NULL; @@ -123,14 +143,21 @@ SRD_PRIV int py_attr_as_strlist(PyObject *py_obj, const char *attr, GSList **out ret = py_listitem_as_str(py_list, i, &outstr); if (ret < 0) { srd_dbg("Couldn't get item %" PY_FORMAT_SIZE_T "d.", i); - return SRD_ERR_PYTHON; + goto err; } *outstrlist = g_slist_append(*outstrlist, outstr); } Py_DECREF(py_list); + PyGILState_Release(gstate); + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -150,18 +177,28 @@ SRD_PRIV int py_dictitem_as_str(PyObject *py_obj, const char *key, char **outstr) { PyObject *py_value; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); if (!PyDict_Check(py_obj)) { srd_dbg("Object is not a dictionary."); - return SRD_ERR_PYTHON; + goto err; } if (!(py_value = PyDict_GetItemString(py_obj, key))) { srd_dbg("Dictionary has no attribute '%s'.", key); - return SRD_ERR_PYTHON; + goto err; } + PyGILState_Release(gstate); + return py_str_as_str(py_value, outstr); + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -181,18 +218,28 @@ SRD_PRIV int py_listitem_as_str(PyObject *py_obj, Py_ssize_t idx, char **outstr) { PyObject *py_value; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); if (!PyList_Check(py_obj)) { srd_dbg("Object is not a list."); - return SRD_ERR_PYTHON; + goto err; } if (!(py_value = PyList_GetItem(py_obj, idx))) { srd_dbg("Couldn't get list item %" PY_FORMAT_SIZE_T "d.", idx); - return SRD_ERR_PYTHON; + goto err; } + PyGILState_Release(gstate); + return py_str_as_str(py_value, outstr); + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -212,26 +259,34 @@ SRD_PRIV int py_pydictitem_as_str(PyObject *py_obj, PyObject *py_key, char **outstr) { PyObject *py_value; + PyGILState_STATE gstate; 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."); - return SRD_ERR_PYTHON; + goto err; } if (!(py_value = PyDict_GetItem(py_obj, py_key))) { srd_dbg("Dictionary has no such key."); - return SRD_ERR_PYTHON; + goto err; } if (!PyUnicode_Check(py_value)) { srd_dbg("Dictionary value should be a string."); - return SRD_ERR_PYTHON; + goto err; } return py_str_as_str(py_value, outstr); + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -249,28 +304,38 @@ SRD_PRIV int py_pydictitem_as_str(PyObject *py_obj, PyObject *py_key, 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; + gstate = PyGILState_Ensure(); + if (!PyDict_Check(py_obj)) { srd_dbg("Object is not a dictionary."); - return SRD_ERR_PYTHON; + goto err; } if (!(py_value = PyDict_GetItem(py_obj, py_key))) { srd_dbg("Dictionary has no such key."); - return SRD_ERR_PYTHON; + goto err; } if (!PyLong_Check(py_value)) { srd_dbg("Dictionary value should be a long."); - return SRD_ERR_PYTHON; + goto err; } *out = PyLong_AsUnsignedLongLong(py_value); + PyGILState_Release(gstate); + return SRD_OK; + +err: + PyGILState_Release(gstate); + + return SRD_ERR_PYTHON; } /** @@ -289,9 +354,13 @@ SRD_PRIV int py_str_as_str(PyObject *py_str, char **outstr) { PyObject *py_bytes; char *str; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); if (!PyUnicode_Check(py_str)) { srd_dbg("Object is not a string object."); + PyGILState_Release(gstate); return SRD_ERR_PYTHON; } @@ -301,11 +370,14 @@ SRD_PRIV int py_str_as_str(PyObject *py_str, char **outstr) Py_DECREF(py_bytes); if (str) { *outstr = str; + PyGILState_Release(gstate); return SRD_OK; } } srd_exception_catch("Failed to extract string"); + PyGILState_Release(gstate); + return SRD_ERR_PYTHON; } @@ -327,22 +399,27 @@ SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv) 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."); - return SRD_ERR_PYTHON; + goto err; } seq_len = PySequence_Size(py_strseq); if (seq_len < 0) { srd_exception_catch("Failed to obtain sequence size"); - return SRD_ERR_PYTHON; + goto err; } strv = g_try_new0(char *, seq_len + 1); if (!strv) { srd_err("Failed to allocate result string vector."); - return SRD_ERR_MALLOC; + ret = SRD_ERR_MALLOC; + goto err; } for (i = 0; i < seq_len; i++) { @@ -374,7 +451,10 @@ err_out: g_strfreev(strv); srd_exception_catch("Failed to obtain string item"); - return SRD_ERR_PYTHON; +err: + PyGILState_Release(gstate); + + return ret; } /** @@ -389,6 +469,9 @@ err_out: 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; @@ -426,5 +509,7 @@ SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj) srd_err("Failed to extract value of unsupported type."); } + PyGILState_Release(gstate); + return var; } |