Don't create wrong wxAppTraits during wxApp construction

Creating wxAppTraits before the object of the user-defined class
deriving from wxApp is fully constructed may result in creating a wrong
traits object if the user class overrides CreateTraits() because the
correct, i.e. user-defined, version isn't used if it's called from wx
code.

This had already happened before and was worked around back in
bc334f39ec (Fixes Bug [ 930200 ] Async does not work, 2004-04-27), but
recently happened again after the changes of 94e4818caa (Warn on startup
when not using comctl32.dll v6 in wxMSW, 2022-11-28). To prevent it from
happening in the future, add WXAppConstructed() that must be called
after fully constructing wxApp (and forgetting to do it would result in
an assert, so doesn't risk to go unnoticed) and which resets m_traits if
it has been wrongly created.

It would, perhaps, be even better if we avoided creating the wrong
traits in the first place, but for now this at least fixes the latest
problem and ensures it doesn't reoccur.

Closes #23315.
This commit is contained in:
Vadim Zeitlin 2023-03-06 19:22:11 +00:00
parent b4256aa4e2
commit 2be5f429c1
9 changed files with 48 additions and 6 deletions

View file

@ -476,6 +476,10 @@ public:
wxCmdLineArgsArray argv;
protected:
// This function must be called at the end of wxApp ctor to indicate that
// wx part of the object is fully constructed.
void WXAppConstructed();
// delete all objects in wxPendingDelete list
//
// called from ProcessPendingEvents()
@ -531,6 +535,11 @@ protected:
// flag modified by Suspend/ResumeProcessingOfPendingEvents()
bool m_bDoPendingEventProcessing = true;
private:
// flag set to true at the end of wxApp ctor, call WXAppConstructed() to
// set it
bool m_fullyConstructed = false;
friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
// the application object is a singleton anyhow, there is no sense in
@ -541,8 +550,11 @@ protected:
#if defined(__UNIX__) && !defined(__WINDOWS__)
#include "wx/unix/app.h"
#else
// this has to be a class and not a typedef as we forward declare it
class wxAppConsole : public wxAppConsoleBase { };
class wxAppConsole : public wxAppConsoleBase
{
public:
wxAppConsole() { WXAppConstructed(); }
};
#endif
// ----------------------------------------------------------------------------

View file

@ -138,10 +138,6 @@ wxAppConsoleBase::wxAppConsoleBase()
#ifdef __WXDEBUG__
SetTraceMasks();
// SetTraceMasks call can cause an apptraits to be
// created, but since we are still in the constructor the wrong kind will
// be created for GUI apps. Destroy it so it can be created again later.
wxDELETE(m_traits);
#endif
wxEvtHandler::AddFilter(this);
@ -162,8 +158,29 @@ wxAppConsoleBase::~wxAppConsoleBase()
// initialization/cleanup
// ----------------------------------------------------------------------------
void wxAppConsoleBase::WXAppConstructed()
{
// Note that we can (and will) be called multiple times for the GUI apps as
// wxAppConsole ctor has to call this function itself too in case it's
// actually a console app, so don't assert that it's currently false.
m_fullyConstructed = true;
// We're called at the end of wxApp ctor execution, i.e. before the
// user-defined wxApp-derived class was fully constructed, so its possibly
// overridden CreateTraits() couldn't have been called yet, which means
// that if we have already initialized our m_traits, we did it wrongly, and
// need to reset it.
if ( m_traits )
{
delete m_traits;
m_traits = nullptr;
}
}
bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **WXUNUSED(argv))
{
wxASSERT_MSG( m_fullyConstructed, "Forgot to call WXAppConstructed()?" );
#if defined(__WINDOWS__)
SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
#endif

View file

@ -26,6 +26,7 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
wxApp::wxApp()
{
WXAppConstructed();
}
wxApp::~wxApp()

View file

@ -308,6 +308,8 @@ wxApp::wxApp()
{
m_isInAssert = false;
m_idleSourceId = 0;
WXAppConstructed();
}
wxApp::~wxApp()

View file

@ -817,6 +817,8 @@ if you believe not using the manifest should remain supported.
);
}
}
WXAppConstructed();
}
wxApp::~wxApp()

View file

@ -379,6 +379,8 @@ wxApp::wxApp()
m_macCurrentEvent = nullptr ;
m_macCurrentEventHandlerCallRef = nullptr ;
m_macPool = sm_isEmbedded ? nullptr : new wxMacAutoreleasePool();
WXAppConstructed();
}
wxApp::~wxApp()

View file

@ -20,6 +20,8 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler);
wxApp::wxApp()
{
m_qtArgc = 0;
WXAppConstructed();
}

View file

@ -74,6 +74,8 @@ private:
wxAppConsole::wxAppConsole()
{
m_signalWakeUpPipe = nullptr;
WXAppConstructed();
}
wxAppConsole::~wxAppConsole()

View file

@ -217,6 +217,8 @@ wxApp::wxApp()
#if !wxUSE_NANOX
m_visualInfo = nullptr;
#endif
WXAppConstructed();
}
wxApp::~wxApp()