`wxApp::OnExit()` may be called before all windows are destroyed (Issue #26172)

33 views
Skip to first unread message

Daniel Collins

unread,
Feb 7, 2026, 7:33:53 PMFeb 7
to wx-...@googlegroups.com, Subscribed
solemnwarning created an issue (wxWidgets/wxWidgets#26172)

Bug description:

I'm not sure how this is getting triggered in the wild, but crash dumps I have on macOS are suggesting that under some condition, my window destructors are running after my app's OnExit() method has been called. I can trigger this on both Linux and macOS by calling wxGetApp().ExitMainLoop() directly from a command handler, which crashes my application because the window destructor tries accessing objects destroyed by my OnExit() method.

Expected vs observed behaviour:

The manual for wxAppConsole::OnExit() states the following:

OnExit is called after destroying all application windows and controls, but before wxWidgets cleanup. Note that it is not called at all if OnInit() failed.

The above is not true if wxApp::ExitMainLoop() is called manually, or seemingly, under some unknown condition on macOS.

Platform and version information

  • wxWidgets version you use: 3.2.8, 3.2.8.1
  • wxWidgets port you use: wxGTK, wxOSX


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172@github.com>

Daniel Collins

unread,
Feb 7, 2026, 7:39:45 PMFeb 7
to wx-...@googlegroups.com, Subscribed
solemnwarning left a comment (wxWidgets/wxWidgets#26172)

I'm not sure if these backtraces will be of much help, but this is the call stack when the condition occurs due to a call to wxApp::ExitMainLoop():

#0  0x00005555559792aa in REHex::MainWindow::~MainWindow (this=0x5555563b8930, __in_chrg=<optimized out>) at src/mainwindow.cpp:676
#1  0x000055555597937e in REHex::MainWindow::~MainWindow (this=0x5555563b8930, __in_chrg=<optimized out>) at src/mainwindow.cpp:678
#2  0x00007ffff746afd6 in wxAppBase::DeleteAllTLWs() () at /lib/x86_64-linux-gnu/libwx_gtk3u_core-3.2.so.0
#3  0x00007ffff746b0a8 in wxAppBase::CleanUp() () at /lib/x86_64-linux-gnu/libwx_gtk3u_core-3.2.so.0
#4  0x00007ffff7b39522 in wxEntryCleanup() () at /lib/x86_64-linux-gnu/libwx_baseu-3.2.so.0
#5  0x00007ffff7b3a04f in wxEntry(int&, wchar_t**) () at /lib/x86_64-linux-gnu/libwx_baseu-3.2.so.0
#6  0x00005555557b0fd2 in main (argc=1, argv=0x7fffffffdfb8) at src/AppMain.cpp:44

And this is a call stack when the mystery trigger (I have crash dumps but cannot reproduce) has happened on macOS:

0   REHex                         	0x000000010448d170 REHex::MainWindow::~MainWindow() + 196
1   REHex                         	0x000000010448d298 REHex::MainWindow::~MainWindow() + 12
2   REHex                         	0x0000000104969c6c wxAppConsoleBase::DeletePendingObjects() + 100
3   REHex                         	0x00000001047d8b90 wxAppBase::CleanUp() + 20
4   REHex                         	0x0000000104756840 wxApp::CleanUp() + 56
5   REHex                         	0x00000001049c3c1c wxEntryCleanup() + 68
6   REHex                         	0x00000001049c3da0 wxEntry(int&, wchar_t**) + 160
7   REHex                         	0x00000001043a5c34 main + 52
8   dyld                          	0x000000018ece9d54 start + 7184


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172/3865841711@github.com>

Daniel Collins

unread,
Feb 7, 2026, 8:14:00 PMFeb 7
to wx-...@googlegroups.com, Subscribed
solemnwarning left a comment (wxWidgets/wxWidgets#26172)

This may actually be a bug in my code, but not a very obvious one. Top-level windows on macOS aren't immediately destroyed, but go into the "pending objects" list to be deleted on the next tick. wxAppBase::Cleanup() features this comment:

    // Clean up any still pending objects. Normally there shouldn't any as we
    // already do this in OnExit(), but this could happen if the user code has
    // somehow managed to create more of them since then or just forgot to call
    // the base class OnExit().
    DeletePendingObjects();

I just checked, and my OnExit() method neglects to call the base class method which has a call to DeletePendingObjects().. in my defence, the documentation isn't explicit about having to call it in your implementation... and then the ordering is questionable - I would expect to have to call it after performing my clean-up, but if I did that, it would already be too late for the window destructor to not crash.

I had a quick look through the samples, and there aren't many that implement wxApp::OnExit(), but the majority which do, also don't call the base class OnExit() method, and the one that does (printing) does so at the end, so would be susceptible to the same crash if it had any window destructors that accessed the g_printData or g_pageSetupData objects.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172/3865883241@github.com>

Daniel Collins

unread,
Feb 8, 2026, 5:47:30 AMFeb 8
to wx-...@googlegroups.com, Subscribed
solemnwarning left a comment (wxWidgets/wxWidgets#26172)

I think I've found the mystery condition on macOS - an uncaught exception causes OnExit() to be called before all the windows are destroyed, even on Linux. Sample program below:

#include <stdexcept>
#include <stdio.h>
#include <wx/wx.h>

class MyFrame: public wxFrame
{
	public:
		MyFrame();
		virtual ~MyFrame() override;
};

class MyApp: public wxApp
{
	public:
		virtual bool OnInit() override;
		virtual int OnExit() override;
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
	new MyFrame();
	return true;
}

int MyApp::OnExit()
{
	wxMessageBox("MyApp::OnExit() called");
	return 0;
}

MyFrame::MyFrame():
	wxFrame(NULL, wxID_ANY, "Test", wxDefaultPosition, wxSize(200, 200))
{
	new wxButton(this, 1, "Throw exception", wxPoint(10, 10));
	Bind(wxEVT_BUTTON, [](wxCommandEvent &event)
	{
		throw std::runtime_error("hello");
	}, 1, 1);
	
	new wxButton(this, 2, "Exit main loop", wxPoint(10, 100));
	Bind(wxEVT_BUTTON, [](wxCommandEvent &event)
	{
		wxGetApp().ExitMainLoop();
	}, 2, 2);
	
	Show();
}

MyFrame::~MyFrame()
{
	wxMessageBox("~MyFrame() called");
}

Closing the window results in the window being destroyed before App::OnExit() is called as documented, pressing either button does the opposite.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172/3866990378@github.com>

VZ

unread,
Feb 13, 2026, 5:21:20 PM (9 days ago) Feb 13
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26172)

Thanks for the reproducer, I do indeed see this even under Linux with wxGTK.

We should fix this by destroying the windows earlier: we postpone doing this because there may be events in flight for these windows, but if the event loop is not running any more, there should be no such events any longer (and if there are any, they're never going to be dispatched anyhow), so it should be fine to destroy the TLWs earlier.

We could also avoid the issues with forgetting to call the base class OnExit() when overriding it by replacing direct calls to it with a wrapper CallOnExit() that would ensure that the windows are destroyed before calling the possibly overridden function.

So I've create the PR linked above doing this and it does make your example behave as expected with wxGTK. Does it also work for you with wxOSX and/or does it need #26157 to be applied for this?

Thanks in advance for testing!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172/3899853517@github.com>

VZ

unread,
Feb 14, 2026, 5:50:44 PM (8 days ago) Feb 14
to wx-...@googlegroups.com, Subscribed

Closed #26172 as completed via f933fee.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/26172/issue_event/22796269164@github.com>

Daniel Collins

unread,
6:03 AM (4 hours ago) 6:03 AM
to wx-...@googlegroups.com, Subscribed
solemnwarning left a comment (wxWidgets/wxWidgets#26172)

@vadz confirmed as working correctly on macOS when f933fee is applied on top of 3.2, thanks!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26172/3940711427@github.com>

Reply all
Reply to author
Forward
0 new messages