This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Tcl event loop callback woes
Type: Stage:
Components: Tkinter Versions:
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: barry, christian.heimes, egnor, gvanrossum, loewis
Priority: normal Keywords:

Created on 2001-08-19 16:34 by egnor, last changed 2022-04-10 16:04 by admin. This issue is now closed.

Messages (6)
msg6059 - (view) Author: Dan Egnor (egnor) Date: 2001-08-19 16:34
I have C code which handles I/O and needs an event
dispatcher.  It is running in the context of a Python
GUI application, and uses the Tcl event loop, using
Tcl_CreateFileHandler and friends.  The C code gets
callbacks from the Tcl event loop fine, but when it
attempts to call into the Python application from one
of these callbacks, things go wrong.

- Tkinter has released the GIL and hidden the current
thread state.  I can work around this by re-acquiring
the GIL from the callback and creating a new thread state.

- When the callback is invoked, Tkinter's tcl_lock is
held.  If the Python code invoked from the callback
ultimately calls some other Tkinter function, the
tcl_lock is still held, and deadlock results.  The only
way to work around this is to use a single-threaded
Python build.

- If the Python code returns an error, there's no way
to stop the event loop to report the error up. 
Tkinter's error-reporting mechanisms are inaccessible.

In general, Tkinter has a lot of infrastructure for
managing callbacks from the Tcl event loop.  If a third
party C library wants to use the same event loop, that
infrastructure is unavailable, and it is very difficult
to work with Python.

Unfortunately, short of using threads (which have their
own problems), there's no other alternative for an
external C library to do I/O without blocking the GUI.
 I've seen several problem reports from people trying
to do exactly this, though they almost never figure out
all of what's going on, and nobody else ever has any
good advice to offer.
msg6060 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2001-08-20 17:02
Logged In: YES 
user_id=12800

For lack of a volunteer or better victim... er, assigning to /F
msg6061 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2001-08-20 18:32
Logged In: YES 
user_id=6380

Unassigning -- /F is a black hole. :-(
msg6062 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2002-02-24 17:26
Logged In: YES 
user_id=21627

It seems that all you need to have is access to the Tcl
lock. Would that solve your problem?

As for reporting the error up: This is certainly possible.
Just implement a _report_exception method on your widget;
define it as

    def _report_exception(self):
        raise
msg6063 - (view) Author: Dan Egnor (egnor) Date: 2002-02-24 17:49
Logged In: YES 
user_id=128950

I *think* external access to the tcl_lock would do it (it's
been a while).  There are a bunch of helper functions/macros
inside the Tkinter code for handling this situation;
exposing and documenting those would be ideal.

As far as error reporting, I don't think that suffices. 
(Again, it's been a while.)  The problem is that the
exception is returned to the C side, which must figure out
what to do with it.  Specifically, the Tcl event loop should
be stopped and the exception reported to whoever invoked
it... but there's no direct way to stop the Tcl event loop.
 (Fuzzy memories here.)
msg59290 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2008-01-05 17:45
The bug report is several years old and probably outdated. Please create
a new issue if you are still interested in the problem.
History
Date User Action Args
2022-04-10 16:04:20adminsetgithub: 35004
2008-01-05 17:45:11christian.heimessetstatus: open -> closed
nosy: + christian.heimes
resolution: out of date
messages: + msg59290
2001-08-19 16:34:31egnorcreate