After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 149093 - gobject.timeout_add from a thread deadlocks
gobject.timeout_add from a thread deadlocks
Status: RESOLVED FIXED
Product: pygtk
Classification: Bindings
Component: gtk
Git Master
Other Linux
: Immediate blocker
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
: 153978 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2004-08-02 19:03 UTC by John Finlay
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gpython.py (5.31 KB, text/plain)
2004-08-02 19:04 UTC, John Finlay
  Details
remove block/unblock threads in gobjectmodule.c:handler_marshal (709 bytes, patch)
2004-08-02 19:46 UTC, Johan (not receiving bugmail) Dahlin
none Details | Review
Simplified testcase (418 bytes, text/plain)
2004-08-02 20:26 UTC, Johan (not receiving bugmail) Dahlin
  Details
Allows gtk_main to be called on any thread (951 bytes, patch)
2004-09-28 20:26 UTC, John Ehresman
none Details | Review

Description John Finlay 2004-08-02 19:03:40 UTC
The latest changes to the threading support in PyGTK 2.3.96 have broken
gpython.py which is the "Interactive GTK Shell" program that I use and recommend
as part of the tutorial. I suspect that this may indicate serious problems in
the threading support.
Comment 1 John Finlay 2004-08-02 19:04:55 UTC
Created attachment 30155 [details]
gpython.py
Comment 2 Johan (not receiving bugmail) Dahlin 2004-08-02 19:46:07 UTC
Created attachment 30156 [details] [review]
remove block/unblock threads in gobjectmodule.c:handler_marshal

This seems to solve it here, can you confirm?

And if you can, try to test it a bit more thoroughly (I've never really used
it, so I'm not sure what to expect/test)
Comment 3 Gustavo Carneiro 2004-08-02 20:05:04 UTC
If you remove pyg_block|unblock_threads then gdk_threads_enter|leave won't ever
be called.

I think a better fix would be (though I haven't tried):
  1. Change implementation of pygdk_block_threads and pygdk_unblock_threads,
replace Py_BLOCK_THREADS and Py_UNBLOCK_THREADS calls with corresponding GIL calls;
  2. From every paired PyGILState_Ensure|Relese, pyg_block|unblock_threads out
there, remove the GIL calls because they'll already be inside
pyg_block|unblock_threads.

  This would also satisfy an additional requirement that I wanted before that no
thread operations will ever get called until the user calls gtk.threads_init(),
thus no performance penalty for single threaded apps.
Comment 4 Johan (not receiving bugmail) Dahlin 2004-08-02 20:24:34 UTC
(Updating summary)

Gustavo: I think, like James mentioned on irc pyg_block|unblock_threads should
go away completely.

For code that calls C->Python (eg PyObject_Call[Method|Object|Function]) we
should use GIL and only Py_BEGIN_ALLOW_THREADS macros for everything else.




Comment 5 Johan (not receiving bugmail) Dahlin 2004-08-02 20:26:06 UTC
Created attachment 30158 [details]
Simplified testcase

Need to figure out how to manage to quit after say 500 ms (because its
obviously a deadlock) if something doesnt happen.
Comment 6 Gustavo Carneiro 2004-08-02 20:39:15 UTC
If we remove pyg_block|unblock_threads, then we have to remove (or deprecate)
gtk.threads_init, and make users call gtk.gdk.threads_enter|leave according to
gtk rules.  Now that's perfectly fine with me (I prefer this, in fact), just
make sure everyone is aware and agrees with this.

Why the comment "Need to figure out how to manage to quit after say 500 ms"? 
Doesn't your test already cover this with SIGALRM?
Comment 7 Gustavo Carneiro 2004-08-02 20:43:52 UTC
Also please note the test only works on unix because of the signal.alarm function.
Comment 8 John Finlay 2004-08-02 20:51:44 UTC
Johan, your fix works for me. I'll continue testing using gpython.py to see if
there are any other problems.
Comment 9 Johan (not receiving bugmail) Dahlin 2004-08-02 21:25:31 UTC
Gustavo: No, they doesn't I tried to use signals, but for some reasons a signal
does not interrupt all other threads. I should probably study threads a bit further.
Comment 10 James Henstridge 2004-08-03 03:39:27 UTC
You should be calling threads_enter()/threads_leave() inside your timeout
function.  The GDK thread lock is not held when timeout functions are called, so
if you are going to call a GTK function in your timeout you need to manually
acquire the lock.

Also, using UNIX async signals for timeouts is likely to cause problems ...
Comment 11 John Finlay 2004-08-03 04:27:01 UTC
The following deadlocks when run in gpython.py:

zippy.stooges.moeraki.com: 295:1295$ gpython.py
Interactive GTK Shell
>>> ls=ListStore(str)
>>> ls.append(['asdf'])
Comment 12 Johan (not receiving bugmail) Dahlin 2004-08-03 14:15:13 UTC
pyg_block/unblock_threads is dead and replaced by BEGIN/END_ALLOW_THREAD macros
and PyGILState.

gpython.py should run unmodified.
Comment 13 Johan (not receiving bugmail) Dahlin 2004-09-28 17:27:09 UTC
*** Bug 153978 has been marked as a duplicate of this bug. ***
Comment 14 Johan (not receiving bugmail) Dahlin 2004-09-28 17:27:42 UTC
This is also a regression in 2.3.97, reopening
Comment 15 John Ehresman 2004-09-28 17:52:28 UTC
The bug with rc1 is that since gtk_main is being called from a thread that was
created with the threading module -- so PyGILState_GetThisThreadState() is
returning NULL.  If we assume that the GIL is held when pyg_enable_threads is
called, we could use the value of the current thread state directly. 
Unfortunately, there's probably C code that calls pyg_enable_threads directly
:(.  We could claim that all such code should first acquire the GIL.
Comment 16 John Ehresman 2004-09-28 20:26:13 UTC
Created attachment 32038 [details] [review]
Allows gtk_main to be called on any thread

This allows gpython to work (at least it doesn't segfault).  It assumes that
the thread calling the pyg_enable_threads C function holds the GIL.
Comment 17 Gustavo Carneiro 2004-09-28 20:32:44 UTC
pyg_enable_threads is called from gobject.threads_init(), thus in this situation
the GIL is held.
It can also be called from external extension modules.  For this, we can just
document this requirement, which seems perfectly reasonable.
Comment 18 John Ehresman 2004-09-29 16:30:14 UTC
Committed 9/28 patch and closing for now.  Will reopen if needed