[issue39093] tkinter objects garbage collected from non-tkinter thread cause panic and core dump

2020-06-15 Thread E. Paine


E. Paine  added the comment:

My initial thoughts were just to give the standard lecture on why "tkinter + 
threads = bad". However, looking again at the problem, the async handler error 
causes the Python interpreter to crash, which, no matter how frowned upon the 
code is, shouldn't happen.

Ultimately, the issue is that a Tkapp object is being deleted in any thread 
other than the one it was created in. I believe there are two parts to the 
solution, both of which are for the Tkapp object in the _tkinter module (as 
there is no guarantee that the user will go through the standard tkinter 
module):

1. If a Tkapp object is created in a thread other than the main and it is made 
global, it is deleted in the main thread as part of the interpreter 
finalisation, not when the thread is finalising. I propose that the Tkapp 
object can only be created in the main thread, helping with part 2.
2. The Tkapp object 'refuses' to delete in a thread other than main, and 
instead gets collected on interpreter finalisation if needed (in the main 
thread).

I don't know how to implement this, but if someone has some ideas, I am more 
than willing to help solidify them into a PR.

Antoine, I hope you are the right person to add to the nosy for this (apologies 
if not).

--
nosy: +epaine, pitrou
versions: +Python 3.10, Python 3.7, Python 3.8, Python 3.9

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39093] tkinter objects garbage collected from non-tkinter thread cause panic and core dump

2019-12-19 Thread obserience


obserience  added the comment:

My proposed fix isn't compatible with a lot of current Tkinter using code. It 
was a naive first attempt and breaks existing code and doesn't completely solve 
the problem.

Variables currently retain a reference to the TCL interpreter self._tk and 
aren't linked into the widget tree or otherwise accessible to any cleanup logic.

Existing code:
-may expect the self.tk attribute of destroyed widgets to still be set

Existing code (after calling root.destroy()):
-calls methods like Tk.quit() which runs Tcl commands requiring self.tk to 
still be there
--Idle does this "# (Needed for clean exit on Windows 98)" <--apparently
---is this still the case??
-may call get() and set() on Variable instances (this currently works)


Given this it might be better to track all references to the TCL interpreter in 
a separate data structure and add a Tk.cleanup() method that gets rid of them 
all with documentation indicating all calls after this will fail. Alternate 
implementation of this deallocates the TCL interpreter in the _tkinter.c 
bindings with the same results.

One of the core issues here is that the cause of the crash is asynchronous 
signal handlers installed by the TCL library and necessary for the TCL 
interpreter to run at all. If you can run TCL commands, the crash can still be 
triggered.

###separate issue###
The Tk.Quit() doc is wrong. Current inline docs say that it destroys all 
widgets, which it does not. All it seems to do is cause mainloop to return 
after which mainloop can be called again and the GUI resumes functioning. This 
has caused problems when the main thread doesn't exit since the GUI continues 
to exist but is frozen. (See quit_behavior.py)

--
Added file: https://bugs.python.org/file48791/quit_behavior.py

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39093] tkinter objects garbage collected from non-tkinter thread cause panic and core dump

2019-12-18 Thread Karthikeyan Singaravelan


Change by Karthikeyan Singaravelan :


--
nosy: +gpolo, serhiy.storchaka

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39093] tkinter objects garbage collected from non-tkinter thread cause panic and core dump

2019-12-18 Thread obserience


obserience  added the comment:

A quick google search for "Tcl_AsyncDelete: async handler deleted by the wrong 
thread" yields plenty of users complaining about this error case. Usually 
they're trying add a gui to an existing application. They run it in a thread 
other than main and then leak a reference to a GUI widget into another thread. 
The GUI exits and then some time later, the last reference to a widget 
dissapears but this is triggered by the leaked reference and occurs in another 
thread context. The TK library panics and the application crashes.

https://github.com/matplotlib/matplotlib/issues/12085
https://github.com/gboeing/osmnx/issues/75
https://stackoverflow.com/questions/27073762/tcl-asyncdelete-error-multithreading-python
(and so on)

The response time and time again is just "you can't run tkinter in any thread 
but main". Hopefully if this fix is implemented, that becomes less true.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39093] tkinter objects garbage collected from non-tkinter thread cause panic and core dump

2019-12-18 Thread obserience


New submission from obserience :

All tkinter objects have a reference to the TCL interpreter object "self.tk". 
The current cleanup code does not remove these when a widget is destroyed.

Garbage collection of the TCL interpreter object occurs only after all gui 
objects are garbage collected. This may  be triggered from another thread 
causing TCL to panic and trigger a core dump.

Error message:
>Tcl_AsyncDelete: async handler deleted by the wrong thread
>Aborted (core dumped)

Adding:
"self.tk = None"
to the end of Misc.destroy() (tkinter/__init__.py line:439) should fix this by 
removing these reference when widgets are destroyed. (Note:destroy is recursive 
on the widget tree and called on the root object when a Tkinter GUI exits)

I can't see any problem with removing the interpreter object from a widget when 
it is destroyed. There doesn't seem to be any way to reassign a widget to a new 
parent so this shouldn't affect anything.

Doing this makes it safe(r) to use tkinter from a non-main thread since if the 
GUI cleans up properly no "landmines" are left to cause a crash when garbage 
collected in the wrong thread.

--
components: Tkinter
files: error_case.py
messages: 358652
nosy: obserience
priority: normal
severity: normal
status: open
title: tkinter objects garbage collected from non-tkinter thread cause panic 
and core dump
type: crash
Added file: https://bugs.python.org/file48789/error_case.py

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com