New submission from John Bollinger <john.bollin...@stjude.org>:

This is the same as issue 452973, created as a new issue pursuant to the 
instruction given when 452973 was closed as "out of date".

In a nutshell, in a program using combining Tkinter with Tcl callbacks written 
in C, it is possible for even a single-threaded program to deadlock.

The case I ran into had these particulars:

The main program is in Python, but it relies on a custom extension written in 
C.  Through that extension, C callbacks are registered for various Tcl GUI 
events, and most of these invoke Python functions via Python's C API.  Many of 
those Python functions invoke Tkinter methods.  For example, many of the 
callbacks are bound to menu item activations, and these typically [try to] 
contruct a Tkinter dialog the first time they are called.  What happens in 
practice is that the program starts fine, but the GUI freezes as soon as any 
menu item is activated that has one of the affected callbacks bound to it.

Gdb and I are confident that the problem is as described in issue 452973: the 
program's single thread acquires TKinter's internal Tcl lock when the mouse 
event processing begins, and does not release it before control re-enters 
Python (there is no public API by which it can be made to do so).  When the 
Python function invokes Tkinter methods, tkinter attempts to acquire the lock 
again, at which point it deadlocks because it holds the lock already.

I encountered this issue on CentOS 6 (thus Python 2.6.6), but it appears that 
the problem is still present in the Python 3 trunk.  I have flagged this issue 
only for version 2.6, however, because I cannot currently confirm that it 
affects later versions (see below regarding testing).

I developed a patch against 2.6.6.  It fixes the problem by allowing the Tcl 
lock to be acquired multiple times by any one thread (and requiring it to be 
released the same number of times before another thread can acquire it).  That 
is perhaps technically inferior to creating public functions around 
_tkinter.c's ENTER_PYTHON and LEAVE_PYTHON macros, but it doesn't touch the 
public API.  Even if new public functions were provided, the reentrant locking 
might still be a good fallback.  The patch applies cleanly to the trunk, so 
probably also to every version between that and 2.6.6.

I would be happy to contribute the patch, but I am a bit at a loss as to how to 
write an automated test for it because (1) such a test must depend on an 
extension module, and (2) test failure means causing a deadlock.

Any advice as to whether such a patch would be considered, or as to how best to 
test it would be welcome.

----------
components: Tkinter
messages: 156619
nosy: jcbollinger
priority: normal
severity: normal
status: open
title: Tkinter single-threaded deadlock
type: behavior
versions: Python 2.6

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue14390>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to