[pygtk] Question about pygtk, threads, python, extension modules and callbacks

Brian dol-sen at telus.net
Tue Mar 14 08:41:07 WST 2006


On Mon, 2006-13-03 at 22:27 +0000, Joao Estevao wrote:
> Hello.
> 
> I'm implementing a pygtk front-end to an extension module that wraps a
> library and I'm having problems.
> 
> It goes something like this:
> 
> The gui creates a thread to run a lengthy and I/O based call.
> The call is made to the extension module and callbacks are invoked,
> through some callback wrappers that will call pygtk code, but are
> meant to be generic and supplyable by the front end.
> 
> What happens now is this. When the call runs in the thread, the front
> end sits there waiting for a threading.Event to be set, and does while
> gtk.events_pending(): gtk.main_iteration().
> So the call goes fine, I can set_fraction a progress bar, but when the
> call to the library performs a C system("ldconfig -r /"), the ui
> freezes, or more generally when some heavy I/O is involved.
> 
> What I do now is, call gtk.threads_init() before the ui starts, then
> in the extension module, and before PyObject_Call, I save the current
> thread state with PyEval_SaveThread, and then after it runs I perform
> a PyEval_RestoreThread, this on the extension module calls that will
> be run in a thread.
> 
> On the callback wrappers, and after a segfault in PyFrame_new or
> something like that, I've figured out that I need to restore the
> thread state again.
> 
> So if anyone would be so kind to explain to me some things about the
> GIL and gtk threads and help me a little bit with this, I'd be very
> thankful.
> 
> I've been running hitting my head against the walls for some time with this.
> 
> Joao.


It is best to run all gui code in the one main thread.  There are
several methods of updating a gui from threads.  For simple short
updates wrapping the gtk calls with the gtk.threads.enter() and leave()
pair works.  For more lengthy updates it is best to pass the information
to be updated to callback code in the gui thread.  Depending on the
complexity of the communication needed there are several choices.  For
complex interaction there is a package called Dispatcher that can pass
signals, etc. between processes, threads, etc.  In our program we have
come up with our own simple dispatcher for inter-thread communication.
It does a nice job of preventing collisions and allows for passing
arbitrary python object(s).


The dispatcher instance can be owned by any thread and can accept input
from any other thread.  For gui updates the dispatcher instance would be
owned by the gui thread and therefore any callback signals received
would then run any desired gui code in the gui thread.  No segfaults due
to data collisions, etc.

For our project :http://sourceforge.net/projects/porthole/
We use it for updating progress bars, and may other callbacks from other
threads.


-- 
Brian <dol-sen at telus.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dispatcher.py
Type: text/x-python
Size: 1251 bytes
Desc: not available
Url : http://www.daa.com.au/pipermail/pygtk/attachments/20060313/e39fe0f1/dispatcher-0001.py
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dispatcher-example.py
Type: text/x-python
Size: 3363 bytes
Desc: not available
Url : http://www.daa.com.au/pipermail/pygtk/attachments/20060313/e39fe0f1/dispatcher-example-0001.py


More information about the pygtk mailing list