Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Using Ctrl-W to close a matplotlib window opened by exec-ing a script in wxpython causes a segfault under linux #3690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MichaelClerx opened this issue Oct 21, 2014 · 8 comments

Comments

@MichaelClerx
Copy link

How to reproduce:

import wx
script = """
import matplotlib.pyplot as pl
import numpy as np

x = np.linspace(0, 1, 100)
y = x ** 1.4
pl.figure()
pl.plot(x, y)
pl.show()
"""
class Main(wx.Frame):
    def __init__(self):
        super(Main, self).__init__(None)
        button = wx.Button(self, wx.ID_ANY, 'Run')
        button.Bind(wx.EVT_BUTTON, self.action_run)
        self.Show()
    def action_run(self, e=None):
        exec(script)
if __name__ == '__main__':
    app = wx.App(False)
    frame = Main()
    app.MainLoop()

Run the application, hit the run button and close the generated graph using Ctrl-W (closing the window in other ways does not crash the application).

It works fine on windows 7 (matplotlib 1.3.1 and wxpython 2.8.12.1 (msw-unicode)) but crashes under linux (matplotlib 1.3.1 and wxpython wx.2.8.12.0 (gtk2-unicode), Fedora 20, Gnome 3.10.2).

Not sure if this is a wx, wxpython or matplotlib bug.

See also:

  1. http://trac.wxwidgets.org/ticket/16622
  2. http://stackoverflow.com/questions/26363208/

Debug output from gdb:

[michael@localhost play]$ gdb --args python segfault-gui.py
GNU gdb (GDB) Fedora 7.7.1-19.fc20
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...Reading symbols from /usr/lib/debug/usr/bin/python2.7.debug...done.
done.
(gdb) r
Starting program: /usr/bin/python segfault-gui.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Traceback (most recent call last):
  File "/usr/share/gdb/auto-load/usr/lib64/libgobject-2.0.so.0.3800.2-gdb.py", line 9, in <module>
    from gobject import register
  File "/usr/share/glib-2.0/gdb/gobject.py", line 3, in <module>
    import gdb.backtrace
ImportError: No module named backtrace
Missing separate debuginfo for /lib64/libgraphite2.so.3
Try: yum --enablerepo='*debug*' install /usr/lib/debug/.build-id/90/82e46860379c3dff9004eb8c9834e50afbb528.debug
[New Thread 0x7fffee6b1700 (LWP 3733)]
[New Thread 0x7fffedeb0700 (LWP 3734)]
[New Thread 0x7fffed6af700 (LWP 3735)]
[New Thread 0x7fffeceae700 (LWP 3736)]
[Thread 0x7fffeceae700 (LWP 3736) exited]

Program received signal SIGSEGV, Segmentation fault.
wxEvtHandler::SearchDynamicEventTable (this=this@entry=0x23e08d0, event=...)
    at src/common/event.cpp:1412
1412            if ((event.GetEventType() == entry->m_eventType) && (entry->m_fn != 0))
(gdb) bt
#0  wxEvtHandler::SearchDynamicEventTable (this=this@entry=0x23e08d0, 
    event=...) at src/common/event.cpp:1412
#1  0x0000003a91ef09f2 in wxEvtHandler::ProcessEvent (this=0x23e08d0, 
    event=...) at src/common/event.cpp:1297
#2  0x0000003a924079f7 in gtk_window_key_press_callback (
    widget=widget@entry=0x10f4170, gdk_event=0x23e66b0, 
    win=win@entry=0x23e08d0) at src/gtk/window.cpp:1034
#3  0x0000003a94b484ec in _gtk_marshal_BOOLEAN__BOXED (closure=0x1fdd550, 
    return_value=0x7fffffffc970, n_param_values=<optimized out>, 
    param_values=0x7fffffffca20, invocation_hint=<optimized out>, 
    marshal_data=<optimized out>) at gtkmarshalers.c:86
#4  0x0000003a81e10298 in g_closure_invoke (closure=0x1fdd550, 
    return_value=return_value@entry=0x7fffffffc970, n_param_values=2, 
    param_values=param_values@entry=0x7fffffffca20, 
    invocation_hint=invocation_hint@entry=0x7fffffffc9c0) at gclosure.c:777
#5  0x0000003a81e2235d in signal_emit_unlocked_R (node=node@entry=0x102b7b0, 
    detail=detail@entry=0, instance=instance@entry=0x10f4170, 
    emission_return=emission_return@entry=0x7fffffffcad0, 
    instance_and_params=instance_and_params@entry=0x7fffffffca20)
    at gsignal.c:3586
#6  0x0000003a81e29ddd in g_signal_emit_valist (instance=<optimized out>, 
    signal_id=<optimized out>, detail=<optimized out>, 
    var_args=var_args@entry=0x7fffffffcbb0) at gsignal.c:3340
#7  0x0000003a81e2a3af in g_signal_emit (instance=instance@entry=0x10f4170, 
    signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3386
#8  0x0000003a94c777a4 in gtk_widget_event_internal (
    widget=widget@entry=0x10f4170, event=event@entry=0x23e66b0)
    at gtkwidget.c:5017
#9  0x0000003a94c77a79 in IA__gtk_widget_event (
    widget=widget@entry=0x10f4170, event=event@entry=0x23e66b0)
    at gtkwidget.c:4814
#10 0x0000003a94c8d2bb in IA__gtk_window_propagate_key_event (
    window=window@entry=0x10645b0, event=event@entry=0x23e66b0)
    at gtkwindow.c:5199
#11 0x0000003a94c8fe13 in gtk_window_key_press_event (widget=0x10645b0, 
    event=0x23e66b0) at gtkwindow.c:5229
#12 0x0000003a94b484ec in _gtk_marshal_BOOLEAN__BOXED (closure=0x102b760, 
    return_value=0x7fffffffce40, n_param_values=<optimized out>, 
    param_values=0x7fffffffcef0, invocation_hint=<optimized out>, 
    marshal_data=<optimized out>) at gtkmarshalers.c:86
#13 0x0000003a81e10298 in g_closure_invoke (closure=closure@entry=0x102b760, 
    return_value=return_value@entry=0x7fffffffce40, n_param_values=2, 
    param_values=param_values@entry=0x7fffffffcef0, 
    invocation_hint=invocation_hint@entry=0x7fffffffce90) at gclosure.c:777
#14 0x0000003a81e2211b in signal_emit_unlocked_R (node=node@entry=0x102b7b0, 
    detail=detail@entry=0, instance=instance@entry=0x10645b0, 
    emission_return=emission_return@entry=0x7fffffffcfa0, 
    instance_and_params=instance_and_params@entry=0x7fffffffcef0)
    at gsignal.c:3624
---Type <return> to continue, or q <return> to quit---
#15 0x0000003a81e29ddd in g_signal_emit_valist (instance=<optimized out>, 
    signal_id=<optimized out>, detail=<optimized out>, 
    var_args=var_args@entry=0x7fffffffd080) at gsignal.c:3340
#16 0x0000003a81e2a3af in g_signal_emit (instance=instance@entry=0x10645b0, 
    signal_id=<optimized out>, detail=detail@entry=0) at gsignal.c:3386
#17 0x0000003a94c777a4 in gtk_widget_event_internal (
    widget=widget@entry=0x10645b0, event=event@entry=0x23e66b0)
    at gtkwidget.c:5017
#18 0x0000003a94c77a79 in IA__gtk_widget_event (
    widget=widget@entry=0x10645b0, event=event@entry=0x23e66b0)
    at gtkwidget.c:4814
#19 0x0000003a94b467e7 in IA__gtk_propagate_event (widget=0x10645b0, 
    event=0x23e66b0) at gtkmain.c:2464
#20 0x0000003a94b46b0b in IA__gtk_main_do_event (event=0x23e66b0)
    at gtkmain.c:1685
#21 0x0000003a9526040c in gdk_event_dispatch (source=source@entry=0x867810, 
    callback=<optimized out>, user_data=<optimized out>)
    at gdkevents-x11.c:2403
#22 0x0000003a80a492a6 in g_main_dispatch (context=0xc1f0b0) at gmain.c:3066
#23 g_main_context_dispatch (context=context@entry=0xc1f0b0) at gmain.c:3642
#24 0x0000003a80a49628 in g_main_context_iterate (context=0xc1f0b0, 
    block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>)
    at gmain.c:3713
#25 0x0000003a80a49a3a in g_main_loop_run (loop=0x10e9ae0) at gmain.c:3907
#26 0x0000003a94b45b57 in IA__gtk_main () at gtkmain.c:1257
#27 0x0000003a923f718a in wxEventLoop::Run (this=0x10f6310)
    at src/gtk/evtloop.cpp:76
#28 0x0000003a92476a3b in wxAppBase::MainLoop (this=this@entry=0xa93950)
    at src/common/appcmn.cpp:312
#29 0x00007ffff14293af in wxPyApp::MainLoop (this=0xa93950)
    at src/helpers.cpp:215
#30 0x00007ffff146a81c in _wrap_PyApp_MainLoop (args=<optimized out>)
    at src/gtk/_core_wrap.cpp:31691
#31 0x00000039a7ce16f2 in ext_do_call (nk=<optimized out>, 
    na=<optimized out>, flags=<optimized out>, pp_stack=0x7fffffffd5a0, 
    func=<built-in function PyApp_MainLoop>)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:4408
#32 PyEval_EvalFrameEx (
    f=f@entry=Frame 0x10f8670, for file /usr/lib64/python2.7/site-packages/wx-2.8-gtk2-unicode/wx/_core.py, line 7306, in MainLoop (args=(<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>,), kwargs={}), throwflag=throwflag@entry=0)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:2779
#33 0x00000039a7ce21dd in PyEval_EvalCodeEx (co=<optimized out>, 
    globals=<optimized out>, locals=locals@entry=0x0, 
    args=args@entry=0x7ffff1751728, argcount=1, kws=kws@entry=0x0, 
    kwcount=kwcount@entry=0, defs=defs@entry=0x0, defcount=defcount@entry=0, 
    closure=0x0) at /usr/src/debug/Python-2.7.5/Python/ceval.c:3330
---Type <return> to continue, or q <return> to quit---
#34 0x00000039a7c6f0d8 in function_call (func=<function at remote 0x827500>, 
    arg=(<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>,), kw=0x0)
    at /usr/src/debug/Python-2.7.5/Objects/funcobject.c:526
#35 0x00000039a7c4a0d3 in PyObject_Call (
    func=func@entry=<function at remote 0x827500>, 
    arg=arg@entry=(<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>,), kw=kw@entry=0x0)
    at /usr/src/debug/Python-2.7.5/Objects/abstract.c:2529
#36 0x00000039a7c590c5 in instancemethod_call (
    func=<function at remote 0x827500>, 
    arg=(<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>,), kw=0x0)
    at /usr/src/debug/Python-2.7.5/Objects/classobject.c:2602
#37 0x00000039a7c4a0d3 in PyObject_Call (
    func=func@entry=<instancemethod at remote 0x8b6280>, 
    arg=arg@entry=(<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>,), kw=kw@entry=0x0)
    at /usr/src/debug/Python-2.7.5/Objects/abstract.c:2529
#38 0x00000039a7cde37c in do_call (nk=<optimized out>, na=1, 
    pp_stack=0x7fffffffdaf0, func=<instancemethod at remote 0x8b6280>)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:4316
#39 call_function (oparg=<optimized out>, pp_stack=0x7fffffffdaf0)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:4121
#40 PyEval_EvalFrameEx (
    f=f@entry=Frame 0x10f84b0, for file /usr/lib64/python2.7/site-packages/wx-2.8-gtk2-unicode/wx/_core.py, line 8010, in MainLoop (self=<App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>), 
    throwflag=throwflag@entry=0)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:2740
#41 0x00000039a7ce0980 in fast_function (nk=<optimized out>, na=1, n=1, 
    pp_stack=0x7fffffffdc50, func=<function at remote 0x8298c0>)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:4184
#42 call_function (oparg=<optimized out>, pp_stack=0x7fffffffdc50)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:4119
#43 PyEval_EvalFrameEx (
    f=f@entry=Frame 0x6cc750, for file segfault-gui.py, line 23, in <module> (), throwflag=throwflag@entry=0)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:2740
#44 0x00000039a7ce21dd in PyEval_EvalCodeEx (co=co@entry=0x7ffff7ed79b0, 
    globals=globals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject a---Type <return> to continue, or q <return> to quit---
t remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, 
    locals=locals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, args=args@entry=0x0, argcount=argcount@entry=0, 
    kws=kws@entry=0x0, kwcount=kwcount@entry=0, defs=defs@entry=0x0, 
    defcount=defcount@entry=0, closure=closure@entry=0x0)
    at /usr/src/debug/Python-2.7.5/Python/ceval.c:3330
#45 0x00000039a7ce22e2 in PyEval_EvalCode (co=co@entry=0x7ffff7ed79b0, 
    globals=globals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, 
    locals=locals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}) at /usr/src/debug/Python-2.7.5/Python/ceval.c:689
#46 0x00000039a7cfb71f in run_mod (mod=<optimized out>, 
    filename=filename@entry=0x7fffffffe3aa "segfault-gui.py", 
    globals=globals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, 
    locals=locals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, ---Type <return> to continue, or q <return> to quit---
y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, flags=flags@entry=0x7fffffffdeb0, 
    arena=arena@entry=0x6b9570)
    at /usr/src/debug/Python-2.7.5/Python/pythonrun.c:1373
#47 0x00000039a7cfc8de in PyRun_FileExFlags (fp=fp@entry=0x6b7bc0, 
    filename=filename@entry=0x7fffffffe3aa "segfault-gui.py", 
    start=start@entry=257, 
    globals=globals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, 
    locals=locals@entry={'script': '\nimport matplotlib.pyplot as pl\nimport numpy as np\n\nx = np.linspace(0, 1, 100)\ny = x ** 1.4\npl.figure()\npl.plot(x, y)\npl.show()\n', '__builtins__': <module at remote 0x7ffff7f7eb08>, '__file__': 'segfault-gui.py', '__package__': None, 'frame': <Main(this=<PySwigObject at remote 0xe86cf0>) at remote 0x7ffff1928d50>, '__name__': '__main__', 'app': <App(this=<PySwigObject at remote 0x7ffff7ef0360>, stdioWin=None, saveStdio=(<file at remote 0x7ffff7f99150>, <file at remote 0x7ffff7f991e0>)) at remote 0x7ffff1977490>, 'Main': <type at remote 0xc86090>, '__doc__': None, 'wx': <module at remote 0x7ffff7ee8910>}, closeit=closeit@entry=1, 
    flags=flags@entry=0x7fffffffdeb0)
    at /usr/src/debug/Python-2.7.5/Python/pythonrun.c:1359
#48 0x00000039a7cfdb69 in PyRun_SimpleFileExFlags (fp=fp@entry=0x6b7bc0, 
    filename=filename@entry=0x7fffffffe3aa "segfault-gui.py", 
    closeit=closeit@entry=1, flags=flags@entry=0x7fffffffdeb0)
    at /usr/src/debug/Python-2.7.5/Python/pythonrun.c:951
#49 0x00000039a7cfe093 in PyRun_AnyFileExFlags (fp=fp@entry=0x6b7bc0, 
    filename=filename@entry=0x7fffffffe3aa "segfault-gui.py", 
    closeit=closeit@entry=1, flags=flags@entry=0x7fffffffdeb0)
    at /usr/src/debug/Python-2.7.5/Python/pythonrun.c:755
#50 0x00000039a7d0eb7f in Py_Main (argc=<optimized out>, argv=<optimized out>)
    at /usr/src/debug/Python-2.7.5/Modules/main.c:640
#51 0x0000003a7ee21d65 in __libc_start_main (main=0x4006f0 <main>, argc=2, 
    argv=0x7fffffffe078, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffe068) at libc-start.c:285
#52 0x0000000000400721 in _start ()
@MichaelClerx
Copy link
Author

Turns out it also happens without any script execution:

#!/usr/bin/env python
import wx
import matplotlib
matplotlib.use('wxAgg')
import matplotlib.pyplot as pl
class Main(wx.Frame):
    def __init__(self):
        super(Main, self).__init__(None)
        button = wx.Button(self, wx.ID_ANY, 'Run')
        button.Bind(wx.EVT_BUTTON, self.action_run)
        self.Show()
    def action_run(self, e=None):
        pl.figure()
        pl.plot([1,2,3,4,5], [3,1,2,5,4])
        pl.show()
if __name__ == '__main__':
    app = wx.App(False)
    frame = Main()
    app.MainLoop()

@tacaswell tacaswell added this to the v1.4.x milestone Nov 26, 2014
@tacaswell
Copy link
Member

I can confirm this.

I suspect that this is related to #3316.

The Qt backends had a similar (but less fatal) issue where the root cause was that things were getting torn down in the wrong, the python and c/c++ layers are getting out of sync as to what still exists and something is trying to use an object that has already been deleted.

Someone who knows the wx frame work needs to trace through how the keybinding call-backs to close the figure are different that the callbacks from the close window button.

@OceanWolf
Copy link
Member

I have come across this bug in my refactor #4143

Almost fixed it, quite a nasty little thing to track down, but I should hopefully have it patched up soon.

@OceanWolf
Copy link
Member

Patch in, I had already fixed it a while ago, but I had gone beyond to the next error that sometimes sits behind the segfault, which I have now tracked down to the canvas (and thus completely unrelated to the refactor, so I shall stop at this point).

I tested the refactor on examples/pylab_examples/xcorr_demo.py and it works fine with Ctrl+w, however... resizing the window causes ../src/gtk/dcclient.cpp(250): assert "Assert failure" failed in wxFreePoolGC(): Wrong GC to show up when python shuts down. The same message shows up on python exit (i.e. after it prints Done) with the following programme giving four of those assert failures per FigureCanvasWx plus extra for any window resizing done:

import matplotlib
matplotlib.use('Wx')
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(5)
y = 2*x

plt.figure()
plt.plot(x,y)

#plt.figure()
#plt.scatter(x,y)

plt.show()

print('Done')

The segmentation bug meant that the application died before ever getting to python clearing up, so these assertion errors never showed up (it also meant that both windows got shut by a single Ctrl+w.

http://mailman.paulmcnett.com/pipermail/floatcanvas/2014-February/001227.html makes it look like this assertion error comes from garbage collection of wx.EmptyBitmap. For anyone wanting to fix this, I suggest looking at that link, I don't have the time (or knowledge about FigureCanvas, wx nor DCs to make it a fast fix for me). I did try commenting out all sections of FigureCanvasWx that refer to wx.EmptyBitmap, i.e. self.bitmap in the context of FigureCanvasWx and the assertion failures disappeared. With the knowledge that xcorr doesn't throw this assertion failure, that should help narrow down the codepath.

P.S. my refactor for wx lies in OceanWolf/matplotlib@backend-refactor...backend-refactor-wx

@OceanWolf
Copy link
Member

Oh, and if you want to see the assert failiure bug on master (or released), just resize and close the window using the close button, as that doesn't trigger the Segfault.

@tacaswell tacaswell modified the milestones: proposed next point release, next point release Jul 17, 2015
@tacaswell
Copy link
Member

Probably related to #3316

@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@DietmarSchwertberger
Copy link
Contributor

This bug is still around, right?
It's probably caused by evt.Skip() being called when the Ctrl-W key handler has destroyed the FigureCanvas already (or actually the parent wx.Frame which in turn destroys ).
Destroying an object which has pending events is a common cause for wx crashes. Later wx/Python versions have a DestroyLater method to postpone destruction until the events are handled.

When I comment evt.Skip() out, I can stop the crash on my Ubuntu VM.
The simplest, least invasive modification would be this one (in backend_wx.py, original comments omitted):

class FigureCanvasWx(FigureCanvasBase, wx.Panel):

    def _onKeyDown(self, evt):
        key = self._get_key(evt)
        FigureCanvasBase.key_press_event(self, key, guiEvent=evt)
        if self:
            evt.Skip()

    def _onKeyUp(self, evt):
        key = self._get_key(evt)
        FigureCanvasBase.key_release_event(self, key, guiEvent=evt)
        if self:
            evt.Skip()

If the underlying C++ object is destroyed, the boolean value of self is False.

Of course it would be better not to call evt.Skip() for any handled key event at all. But FigureCanvasBase.key_press_event() does probably not return this information, right?
Completely omitting it may break compatibility somewhere, but I'm not sure about that. It could be the best solution.

I also tried calling the frame's Destroy method via wx.CallAfter and also DestroyLater on wxPython 4 but that was not effective.

@MichaelClerx: could you please try this? If it is effective for you and not better solution shows up, then I will submit a pull request.

@MichaelClerx
Copy link
Author

Thanks @DietmarSchwertberger

It's been a while, so I checked and the original example still produces a segfault on Fedora 26, Python 2.7.14, Matplotlib 2.0.0, wx 3.0.2.0 gtk3 (classic).

I then made the changes to backend_wx.py you suggested, and this seems to resolve the issue!

@DietmarSchwertberger DietmarSchwertberger self-assigned this Feb 11, 2018
DietmarSchwertberger added a commit to DietmarSchwertberger/matplotlib that referenced this issue Feb 11, 2018
@QuLogic QuLogic modified the milestones: needs sorting, v2.2.0 Feb 12, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants