Package: python-zbar Version: 0.10+doc-10 Severity: wishlist Tags: upstream patch
As discussed in http://sourceforge.net/p/zbar/bugs/48/ the Python bindings for zbar do not support threading, meaning it's not possible to build multithreaded Python tools supporting asynchronous scanning. There is an upstream fix at: http://sourceforge.net/p/zbar/code/ci/1c14e19910e96fe132897db8343b24179265f3ef which I have added on top of the zbar 0.10+doc-9 package and confirmed fixes the issue I see; I attach it to this bug report as well (I dropped it in debian/patches/ and added it to debian/patches/series for building). Please consider including this fix with the next package upload. Thanks. -- System Information: Debian Release: jessie/sid APT prefers testing APT policy: (900, 'testing'), (800, 'unstable'), (500, 'testing-updates'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.17.0+ (SMP w/4 CPU cores) Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages python-zbar depends on: ii libc6 2.19-11 ii libjpeg8 8d1-2 ii libv4l-0 1.6.0-1+b1 ii libzbar0 0.10+doc-10 ii python 2.7.8-1 python-zbar recommends no packages. python-zbar suggests no packages. -- no debconf information
--- a/python/processor.c 2009-10-23 19:16:44.000000000 +0100 +++ b/python/processor.c 2014-07-29 18:22:52.706154561 +0100 @@ -36,15 +36,24 @@ PyObject *args, PyObject *kwds) { - static char *kwlist[] = { NULL }; - if(!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) + static char *kwlist[] = { "enable_threads", NULL }; + int threaded = -1; + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|O&", kwlist, + object_to_bool, &threaded)) + return(NULL); + +#ifndef WITH_THREAD + if(threaded > 0 && + PyErr_WarnEx(NULL, "threading requested but not available", 1)) return(NULL); + threaded = 0; +#endif zbarProcessor *self = (zbarProcessor*)type->tp_alloc(type, 0); if(!self) return(NULL); - self->zproc = zbar_processor_create(0/*FIXME*/); + self->zproc = zbar_processor_create(threaded); zbar_processor_set_userdata(self->zproc, self); if(!self->zproc) { Py_DECREF(self); @@ -228,7 +237,11 @@ object_to_timeout, &timeout)) return(NULL); - int rc = zbar_processor_user_wait(self->zproc, timeout); + int rc = -1; + Py_BEGIN_ALLOW_THREADS + rc = zbar_processor_user_wait(self->zproc, timeout); + Py_END_ALLOW_THREADS + if(rc < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); @@ -245,7 +258,11 @@ object_to_timeout, &timeout)) return(NULL); - int rc = zbar_process_one(self->zproc, timeout); + int rc = -1; + Py_BEGIN_ALLOW_THREADS + rc = zbar_process_one(self->zproc, timeout); + Py_END_ALLOW_THREADS + if(rc < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(rc)); @@ -265,7 +282,11 @@ if(zbarImage_validate(img)) return(NULL); - int n = zbar_process_image(self->zproc, img->zimg); + int n = -1; + Py_BEGIN_ALLOW_THREADS + n = zbar_process_image(self->zproc, img->zimg); + Py_END_ALLOW_THREADS + if(n < 0) return(zbarErr_Set((PyObject*)self)); return(PyInt_FromLong(n)); @@ -275,6 +296,9 @@ process_handler (zbar_image_t *zimg, const void *userdata) { + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + zbarProcessor *self = (zbarProcessor*)userdata; assert(self); assert(self->handler); @@ -285,7 +309,7 @@ img = zbarImage_FromImage(zimg); if(!img) { PyErr_NoMemory(); - return; + goto done; } } else @@ -299,8 +323,17 @@ PyTuple_SET_ITEM(args, 2, self->closure); PyObject *junk = PyObject_Call(self->handler, args, NULL); - Py_XDECREF(junk); + if(junk) + Py_DECREF(junk); + else { + PySys_WriteStderr("in ZBar Processor data_handler:\n"); + assert(PyErr_Occurred()); + PyErr_Print(); + } Py_DECREF(args); + +done: + PyGILState_Release(gstate); } static PyObject*