msg207599 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-01-07 20:57 |
When run IDLE with file name as agument
$ ./python -m idlelib.idle Lib/decimal.py
and then close or exit it, following traceback is printed:
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0xb5ead62c>>
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/idlelib/MultiCall.py", line 230, in __del__
File "/home/serhiy/py/cpython/Lib/tkinter/__init__.py", line 1043, in unbind
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0xb5eab92c>>
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/idlelib/MultiCall.py", line 230, in __del__
File "/home/serhiy/py/cpython/Lib/tkinter/__init__.py", line 1043, in unbind
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0xb5ea4e4c>>
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/idlelib/MultiCall.py", line 230, in __del__
File "/home/serhiy/py/cpython/Lib/tkinter/__init__.py", line 1043, in unbind
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0xb5ea46ec>>
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/idlelib/MultiCall.py", line 230, in __del__
File "/home/serhiy/py/cpython/Lib/tkinter/__init__.py", line 1043, in unbind
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
This is occurred only in 3.4.
|
msg210297 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-05 10:24 |
Confirmed on OSX 10.8 with Python 3.4 (built from default branch, changeset 88969:32af4954e46a).
Note that this doesn't happen when opening just a shell window, e.g. by running ./python -m idlelib.idle. Furthermore, even when running IDLE as described in the OP, if I open a shell window and then close, I don't get an exception.
|
msg210298 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-05 10:33 |
This is caused by MultiCall's _ComplexBinder.__del__() being called during app shutdown. _ComplexBinder.__del__() unbinds a bunch of event handlers from the widget to which it is attached. It seems that there's some edge case here where the underlying Tk widget has already been destroyed.
Instead of trying to debug all of the Tk events and app shutdown order, I propose just surrounding this __del__() code with a try/except block, catching _tkinter.TclError and ignoring it. From my (somehwat limited) understanding of MultiCall, this shouldn't do any harm.
See attached patch.
|
msg210300 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-02-05 11:18 |
1. try/except should be inside a loop, not outside.
2. It would be better not to hide the problem under the rug, but find why the order of destruction is different when open shell window. Of course, if better solution will not be found, we will have to apply this patch before 3.4 releasing.
|
msg210304 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-05 11:43 |
I put the try/except outside of the loop on purpose. If calling the widget's unbind() method fails once, it will fail forever afterwards.
If you prefer a different spelling, move the try/except into the loop, and break out of the loop in case of an exception:
for seq, id in self.handlerids:
try:
self.widget.unbind(self.widgetinst, seq, id)
except _tkinter.TclError:
break
As for avoiding the exception in the first place, I'm sure figuring out how IDLE shuts down would be a lot of work, and I honestly don't think it's necessary. Note that this problem is triggered in a __del__() method; making sure these are called at a proper time is problematic because the timing depends on the GC.
|
msg210307 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-05 12:44 |
Attaching second patch, to replace the first.
As suggested by Serhiy, I moved the try/except block into the loop.
I also added a comment explaining the try/except block and referencing this issue.
|
msg210308 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-05 12:50 |
Both previous patches caused an import error. Here's a new patch with that fixed, and actually tested to fix the bug.
|
msg210312 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-02-05 13:38 |
I tried all three versions both installed and recent repository builds and verified that the overt issue is limited to 3.4. I agree that the exception message suggests stopping with the first exception. Since there is a small cost to try: and break, I am inclined to move the try back out of the loop. The only thing it could mask is a problem with self.handlerids, and I would expect that if that is corrupted or missing, there would be problems before shutdown.
I know that in 3.4, shutdown order has been modified and the wording of the warning was discussed on pydev. I do not know (and do not care at the moment) if either ignoring __del__ exceptions or warning about them is new in 3.4. What I do remember from the discussion is agreement that 1. __del__ exceptions should be caught so shutdown can continue; 2. a warning should be given in case the exception indicates a bug in __del__; and 3. __del__ writers are responsible to catch exceptions that do not indicate a bug, so as to avoid the warning. So I am inclined to backport to all versions.
|
msg210361 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-02-06 04:55 |
More thoughts: The reason for explicit __del__ is to release memory resources connected to other objects or structures at the behest of the Python instance being deleted. If __del__ were only called at shutdown, it would not be needed, as all memory is released anyway and we could delete __del__. If __del__ is called before shutdown (as would happen if the class were unittested) then exceptions would indicate a bug and should not be ignored. From this viewpoint, not only should the try: except: be within the loop, but the break should be conditioned on the exception message.
if exc.args[0] == 'can't invoke "bind" command: application has been destroyed': break
The modern solution to this dilemma is to use .close instead of .__del__ and either explicitly call .close or have it called in the .__exit__ method of a context manager. For Idle classes, this would not be a problem for future test code, but it would be much trickier finding all places in current code where instances of a class with a .__del__ method get deleted. So a compromise patch with conditioned break seems most practical.
I tried a few more experiments: run the .py file (F5, to create a Shell window) and then close both windows. Whether the closing was shell first or editor first, the messages do not appear. Three runs with -n gave the same results. So it seems that the problem only appears when there has never been a shell window. I agree with Serhiy (his point 2) that this is disconcerting and could indicate a 3.4-specific problem with Tk, tkinter, or Idle.
|
msg210600 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-02-08 09:40 |
I checked that -m idlelib acts the same as -m idlelib.idle, and that there is still a problem after opening a second editor window after the original. So the messages seem tied to not opening a shell window. In testing the patch, I noticed that exceptions are now occurring in all three .__del__ methods. With the candidate release imminent, I decided to only fix what is broken and only apply to 3.4 and not worry now about possible merge problems in the future.
|
msg210603 - (view) |
Author: Roundup Robot (python-dev)  |
Date: 2014-02-08 09:48 |
New changeset f9f2c57f7d00 by Terry Jan Reedy in branch 'default':
Issue #20167: Suppress 3.4 specific 'Exception ignored' messages.
http://hg.python.org/cpython/rev/f9f2c57f7d00
|
msg210861 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-02-10 18:48 |
Changes for _SimpleBinder.__del__ look doubtful. Any TclError exception is suppressed and "if" statement does nothing. Perhaps you forgot "else: raise"? And may be in other places too.
|
msg210872 - (view) |
Author: Roundup Robot (python-dev)  |
Date: 2014-02-10 21:47 |
New changeset b9e124851e47 by Terry Jan Reedy in branch 'default':
Issue #20167: Add missing else: break in 3 places as noticed by Serhiy.
http://hg.python.org/cpython/rev/b9e124851e47
|
msg211130 - (view) |
Author: Tal Einat (taleinat) *  |
Date: 2014-02-13 06:12 |
Good catches, Terry and Serhiy!
|
msg212332 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-02-27 00:09 |
This has been left open to see if the undlying problem can be found. If #20567 is a guide, there might be a root.destroy that should be followed by del root.
|
msg228941 - (view) |
Author: Rusi (RusiMody) |
Date: 2014-10-10 02:01 |
Just confirming:
idle 3.4.1-1 on debian testing
Start idle3
Open recent file -> some file
Close file
Close interpreter (and idle)
Get this
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0x7fc53638f4e0>>
Traceback (most recent call last):
File "/usr/lib/python3.4/idlelib/MultiCall.py", line 244, in __del__
self.widget.unbind(self.widgetinst, seq, id)
File "/usr/lib/python3.4/tkinter/__init__.py", line 1071, in unbind
self.tk.call('bind', self._w, sequence, '')
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0x7fc5363b7240>>
Traceback (most recent call last):
File "/usr/lib/python3.4/idlelib/MultiCall.py", line 244, in __del__
self.widget.unbind(self.widgetinst, seq, id)
File "/usr/lib/python3.4/tkinter/__init__.py", line 1071, in unbind
self.tk.call('bind', self._w, sequence, '')
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0x7fc5363b75f8>>
Traceback (most recent call last):
File "/usr/lib/python3.4/idlelib/MultiCall.py", line 244, in __del__
self.widget.unbind(self.widgetinst, seq, id)
File "/usr/lib/python3.4/tkinter/__init__.py", line 1071, in unbind
self.tk.call('bind', self._w, sequence, '')
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
Exception ignored in: <bound method _ComplexBinder.__del__ of <idlelib.MultiCall._ComplexBinder object at 0x7fc5363b79b0>>
Traceback (most recent call last):
File "/usr/lib/python3.4/idlelib/MultiCall.py", line 244, in __del__
self.widget.unbind(self.widgetinst, seq, id)
File "/usr/lib/python3.4/tkinter/__init__.py", line 1071, in unbind
self.tk.call('bind', self._w, sequence, '')
_tkinter.TclError: can't invoke "bind" command: application has been destroyed
|
msg228943 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-10-10 02:50 |
The problem is the change in the exception message between these two lines
can't invoke "bind" command: application has been destroyed
can't invoke "bind" command: application has been destroyed
In your copy of MultiCall.py, line 63-4, change
APPLICATION_GONE = '''\
can't invoke "bind" command: application has been destroyed'''
by changing ' ' to ' '.
I will reduce the string to "application has been destroyed" and the check from equality to containment.
|
msg228944 - (view) |
Author: Roundup Robot (python-dev)  |
Date: 2014-10-10 03:14 |
New changeset ce0316007b21 by Terry Jan Reedy in branch '3.4':
Issue #20167: revise condition to accomodate message change.
https://hg.python.org/cpython/rev/ce0316007b21
|
msg228946 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-10-10 03:16 |
I verified that problem had returned on Windows as well. It would be good to have a test that would fail if the tcl error message changed again.
|
msg228947 - (view) |
Author: Rusi (RusiMody) |
Date: 2014-10-10 03:20 |
On Fri, Oct 10, 2014 at 8:46 AM, Terry J. Reedy <report@bugs.python.org> wrote:
>
> Terry J. Reedy added the comment:
>
> I verified that problem had returned on Windows as well. It would be good to have a test that would fail if the tcl error message changed again.
>
> ----------
> resolution: fixed ->
> stage: needs patch -> test needed
> versions: +Python 3.5
It is failing again!!
Version 3.4.1-1: checked that removing that space makes the error go away.
Then saw that there is a new version 3.4.2~rc1-1 (almost certainly not
containing your change) in the debian repos.
Upgrading to that has made the error return!
|
msg228948 - (view) |
Author: Rusi (RusiMody) |
Date: 2014-10-10 03:25 |
On Fri, Oct 10, 2014 at 8:49 AM, Rustom Mody <rustompmody@gmail.com> wrote:
> On Fri, Oct 10, 2014 at 8:46 AM, Terry J. Reedy <report@bugs.python.org> wrote:
>>
>> Terry J. Reedy added the comment:
>>
>> I verified that problem had returned on Windows as well. It would be good to have a test that would fail if the tcl error message changed again.
>>
>> ----------
>> resolution: fixed ->
>> stage: needs patch -> test needed
>> versions: +Python 3.5
>
> It is failing again!!
>
> Version 3.4.1-1: checked that removing that space makes the error go away.
> Then saw that there is a new version 3.4.2~rc1-1 (almost certainly not
> containing your change) in the debian repos.
>
> Upgrading to that has made the error return!
By which I meant to say not that it has 'returned'
But that its there in 3.4.2 as well
|
msg228952 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-10-10 05:44 |
I know. 3.4.2.rc1 was released over 2 weeks ago and 3.4.2 just yesterday (essentially without change). So you have to delete space again. Since 3.4.1 worked for many people, perhaps you have an ancient version of tk. You can get major/minor number with
>>> import tkinter as tk
>>> tk.TclVersion
8.6
but 8.5 covers a long time span and many fixes. I forget how to get the third, micro number.
|
msg228953 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-10-10 06:06 |
> I forget how to get the third, micro number.
tkinter.Tcl().call('info', 'patchlevel')
|
msg228954 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-10-10 06:26 |
On 3.5 the issue is gone, but on 3.4 and 2.7 following traceback are generated:
$ ./python -m idlelib.idle Lib/decimal.py
Traceback (most recent call last):
File "/home/serhiy/py/cpython-3.4/Lib/runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
File "/home/serhiy/py/cpython-3.4/Lib/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/serhiy/py/cpython-3.4/Lib/idlelib/idle.py", line 11, in <module>
idlelib.PyShell.main()
File "/home/serhiy/py/cpython-3.4/Lib/idlelib/PyShell.py", line 1562, in main
if flist.open(filename) is None:
File "/home/serhiy/py/cpython-3.4/Lib/idlelib/FileList.py", line 36, in open
edit = self.EditorWindow(self, filename, key)
File "/home/serhiy/py/cpython-3.4/Lib/idlelib/PyShell.py", line 141, in __init__
self.color_breakpoint_text()
File "/home/serhiy/py/cpython-3.4/Lib/idlelib/PyShell.py", line 159, in color_breakpoint_text
self.text.tag_config('BREAK', cfg)
AttributeError: 'NoneType' object has no attribute 'tag_config'
|
msg228956 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-10-10 06:55 |
The above appears to be a system-specific open issue, not a close issue. So it must be a different issue.
On my Win7
F:\Python\dev\4\py34\PCbuild>python_d -m idlelib ../Lib/decimal.py
<close after open with freshly built 3.4.2+>
F:\Python\dev\4\py34\PCbuild>
C:\Programs\Python34>python -m idlelib Lib/decimal.py
<ditto for installed 3.4.2
C:\Programs\Python34>
With a bad file name, I get a blank editor.
In any case, the traceback makes no sense. Before "self.color_breakpoint_text()" in __init__ are 3 "self.text.bind" statements. So self.text = None seems implausible.
|
msg228957 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-10-10 07:07 |
> In any case, the traceback makes no sense. Before
> "self.color_breakpoint_text()" in __init__ are 3 "self.text.bind"
> statements. So self.text = None seems implausible.
The code runs up to self.text.update() in restore_file_breaks() and runs
further only after windows closing. At this time self.text already is None.
|
msg228958 - (view) |
Author: Serhiy Storchaka (serhiy.storchaka) *  |
Date: 2014-10-10 07:14 |
Changing update() to update_idletasks() fixes the issue. But we should
investigate why all works on 3.5 and is there downside of this change.
|
msg229106 - (view) |
Author: Terry J. Reedy (terry.reedy) *  |
Date: 2014-10-11 22:23 |
Serhiy, I responded to your report and followups on a new issue, #22614.
Tal, if you can, please test ./python -m idlelib.idle Lib/decimal.py on OSX and respond there.
|
|
Date |
User |
Action |
Args |
2022-04-11 14:57:56 | admin | set | github: 64366 |
2014-10-11 22:23:03 | terry.reedy | set | status: open -> closed resolution: fixed messages:
+ msg229106
stage: test needed -> resolved |
2014-10-10 07:14:12 | serhiy.storchaka | set | messages:
+ msg228958 |
2014-10-10 07:07:04 | serhiy.storchaka | set | messages:
+ msg228957 |
2014-10-10 06:55:05 | terry.reedy | set | messages:
+ msg228956 |
2014-10-10 06:26:01 | serhiy.storchaka | set | messages:
+ msg228954 versions:
+ Python 2.7 |
2014-10-10 06:06:37 | serhiy.storchaka | set | messages:
+ msg228953 |
2014-10-10 05:44:29 | terry.reedy | set | messages:
+ msg228952 |
2014-10-10 03:25:56 | RusiMody | set | messages:
+ msg228948 |
2014-10-10 03:20:14 | RusiMody | set | messages:
+ msg228947 |
2014-10-10 03:16:17 | terry.reedy | set | resolution: fixed -> (no value) stage: needs patch -> test needed messages:
+ msg228946 versions:
+ Python 3.5 |
2014-10-10 03:14:13 | python-dev | set | messages:
+ msg228944 |
2014-10-10 02:50:39 | terry.reedy | set | messages:
+ msg228943 |
2014-10-10 02:01:49 | RusiMody | set | nosy:
+ RusiMody messages:
+ msg228941
|
2014-02-27 00:09:54 | terry.reedy | set | resolution: fixed messages:
+ msg212332 stage: needs patch |
2014-02-13 06:12:21 | taleinat | set | messages:
+ msg211130 |
2014-02-10 21:47:04 | python-dev | set | messages:
+ msg210872 |
2014-02-10 18:48:56 | serhiy.storchaka | set | messages:
+ msg210861 |
2014-02-08 09:48:00 | python-dev | set | nosy:
+ python-dev messages:
+ msg210603
|
2014-02-08 09:40:21 | terry.reedy | set | assignee: terry.reedy messages:
+ msg210600 |
2014-02-06 04:55:22 | terry.reedy | set | messages:
+ msg210361 |
2014-02-05 13:38:51 | terry.reedy | set | messages:
+ msg210312 |
2014-02-05 12:50:46 | taleinat | set | files:
+ taleinat_idle_closing_exception_3.patch
messages:
+ msg210308 |
2014-02-05 12:44:14 | taleinat | set | files:
+ taleinat_idle_closing_exception_2.patch
messages:
+ msg210307 |
2014-02-05 11:43:38 | taleinat | set | messages:
+ msg210304 |
2014-02-05 11:18:44 | serhiy.storchaka | set | messages:
+ msg210300 |
2014-02-05 10:33:23 | taleinat | set | files:
+ taleinat_idle_closing_exception.patch keywords:
+ patch messages:
+ msg210298
|
2014-02-05 10:24:41 | taleinat | set | nosy:
+ taleinat messages:
+ msg210297
|
2014-01-07 20:57:38 | serhiy.storchaka | create | |