Segfault on Linux

I have a wx.grid.Grid with a custom wx.grid.GridTableBase subclass. When I update the data it works fine, but when I subsequently close the application I get a segfault (see below).

In my subclass I’ve reimplemented GetNumberRows(), GetNumberCols(), GetValue(), SetValue(), GetColLabelValue() and GetRowLabelValue(). Are there any other methods I should be implementing?

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffe84ce700 (LWP 5756)]
[New Thread 0x7fffe7ccd700 (LWP 5757)]
[New Thread 0x7fffe71fb700 (LWP 5758)]
Traceback (most recent call last):
  File "./MyApp.pyw", line 31, in <module>
    main()
  File "./MyApp.pyw", line 27, in main
    app.MainLoop()
  File "/usr/lib/python3/dist-packages/wx/core.py", line 2096, in MainLoop
    rv = wx.PyApp.MainLoop(self)
wx._core.wxAssertionError: C++ assertion "GetEventHandler() == this" failed at ../src/common/wincmn.cpp(478) in ~wxWindowBase(): any pushed event handlers must have been removed
../src/common/wincmn.cpp(1463): assert "firstHandler->GetPreviousHandler() == __null" failed in PopEventHandler(): the first handler of the wxWindow stack should have no previous handlers set

Thread 1 "python3" received signal SIGSEGV, Segmentation fault.
0x0000000000000002 in ?? ()
(gdb) bt
#0  0x0000000000000002 in  ()
#1  0x00007fffe9cc27e7 in wxGridCellEditor::Destroy() () at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#2  0x00007fffe9cc4506 in wxGridCellEditor::~wxGridCellEditor() () at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#3  0x00007fffe9ccb62a in  () at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#4  0x00007fffe9fecc37 in non-virtual thunk to wxGridCellAttr::~wxGridCellAttr() ()
    at /usr/lib/python3/dist-packages/wx/_grid.cpython-36m-x86_64-linux-gnu.so
#5  0x00007fffe9c9ada1 in wxGridRowOrColAttrData::~wxGridRowOrColAttrData() ()
    at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#6  0x00007fffe9c9ae57 in wxGridCellAttrProvider::~wxGridCellAttrProvider() ()
    at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#7  0x00007fffe9c9aece in wxGridCellAttrProvider::~wxGridCellAttrProvider() ()
    at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#8  0x00007fffe9c9b780 in wxGridTableBase::~wxGridTableBase() () at /usr/lib/x86_64-linux-gnu/libwx_gtk3u_adv-3.0.so.0
#9  0x00007fffea010c29 in sipwxGridTableBase::~sipwxGridTableBase() ()
    at /usr/lib/python3/dist-packages/wx/_grid.cpython-36m-x86_64-linux-gnu.so
#10 0x00007fffea01119d in  () at /usr/lib/python3/dist-packages/wx/_grid.cpython-36m-x86_64-linux-gnu.so
#11 0x00007fffea3e72a9 in  () at /usr/lib/python3/dist-packages/sip.cpython-36m-x86_64-linux-gnu.so
#12 0x00007fffea3e72b9 in  () at /usr/lib/python3/dist-packages/sip.cpython-36m-x86_64-linux-gnu.so
#13 0x000000000053dbec in  ()
#14 0x0000000000552922 in  ()
#15 0x00007fffea3e6d27 in  () at /usr/lib/python3/dist-packages/sip.cpython-36m-x86_64-linux-gnu.so
#16 0x00007fffea3e6e34 in  () at /usr/lib/python3/dist-packages/sip.cpython-36m-x86_64-linux-gnu.so
#17 0x00007fffea3e72c1 in  () at /usr/lib/python3/dist-packages/sip.cpython-36m-x86_64-linux-gnu.so
#18 0x000000000053dbec in  ()
#19 0x000000000056fa08 in  ()
#20 0x00000000005b3567 in  ()
#21 0x00000000005b3584 in  ()
#22 0x000000000054d1fc in  ()
#23 0x00000000005642ab in PyDict_SetItemString ()
#24 0x00000000004cb4e6 in PyImport_Cleanup ()
#25 0x000000000064314e in Py_FinalizeEx ()
#26 0x000000000062b06e in Py_Main ()
#27 0x00000000004b4cb0 in main ()
(gdb) 

It also crashes on Windows 10:

Traceback (most recent call last):
  File "MyApp.pyw", line 31, in <module>
    main()
  File "MyApp.pyw", line 27, in main
    app.MainLoop()
  File "C:\bin\python\lib\site-packages\wx\core.py", line 2166, in MainLoop
    rv = wx.PyApp.MainLoop(self)
wx._core.wxAssertionError: C++ assertion "GetEventHandler() == this" failed at ..\..\src\common\wincmn.cpp(478) in wxWindowBase::~wxWindowBase(): any pushed event handlers must have been removed

Errors like this usually indicate that there is a problem with reference counts of grid editor, renderer, and/or attributes. Some of the Grid C++ classes use an internal ref-counting scheme to manage sharing and lifetime of the editor, rendere and attr objects. Unfortunately it doesn’t work exactly the same as Python’s ref-counting patterns so it’s easy to get things wrong when thinking about it from a Python perspective.

If you can replicate the problem in a small runnable sample then I can take a look at it. Otherwise, the things to investigate are anywhere you are using one of the mentioned classes. Based on the stack trace and assertion then it is obviously a problem with a GridCellEditor, but keep in mind that GridCellAttr objects also have a reference to a GridCellEditor, so the ref-count issue could be with the attr object as well. You can use the GetRefCount() method to help with the debugging.

In general, if you want to hold on to an editor or attr in order to reuse it in other cells, then you’ll need to call its IncRef method. But then you’ll need to ensure that you call its DecRef method before the grid objects it is used in are destroyed to ensure that it will be properly cleaned up in the right order. Otherwise if you always create a new instance then you will probably be okay without using IncRef, but you may want to use GetRefCount to double check if in doubt.