Don't use wx_ptr for the splash screen.
authorCarl Hetherington <cth@carlh.net>
Tue, 25 Apr 2023 09:03:54 +0000 (11:03 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 25 Apr 2023 09:03:56 +0000 (11:03 +0200)
Using wx_ptr in the wxApp object seems bad because in ~App wxWidgets
deletes all top-level windows in `DeleteAllTLWs` so if ~wx_ptr then
tries to destroy them we get a use-after-free.

src/tools/dcpomatic.cc
src/tools/dcpomatic_editor.cc
src/tools/dcpomatic_kdm.cc
src/tools/dcpomatic_player.cc
src/wx/wx_util.cc
src/wx/wx_util.h

index a7b3af8bce0999f44d4c420163988fccc72372ad..3d944e780a9358cbbe828e6d2f050d11d73ceaf6 100644 (file)
@@ -1709,7 +1709,7 @@ private:
                }
                catch (exception& e)
                {
-                       _splash.reset();
+                       close_splash();
                        error_dialog (nullptr, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what()));
                }
 
@@ -1821,7 +1821,8 @@ private:
 
        void close_splash ()
        {
-               _splash.reset();
+               _splash->Destroy();
+               _splash = nullptr;
        }
 
        void config_failed_to_load (Config::LoadFailure what)
@@ -1839,7 +1840,7 @@ private:
                /* Destroy the splash screen here, as otherwise bad things seem to happen (for reasons unknown)
                   when we open our recreate dialog, close it, *then* try to Destroy the splash (the Destroy fails).
                */
-               _splash.reset();
+               close_splash();
 
                auto config = Config::instance();
                switch (reason) {
@@ -1908,7 +1909,7 @@ private:
        }
 
        DOMFrame* _frame = nullptr;
-       wx_ptr<wxSplashScreen> _splash;
+       wxSplashScreen* _splash;
        shared_ptr<wxTimer> _timer;
        string _film_to_load;
        string _film_to_create;
index 663eb8e3b00a4d2917846471799a911fea7cd226..a61a17ce4ff74eb8cd80680b07c7392cdac43937 100644 (file)
@@ -428,7 +428,7 @@ private:
 
        bool OnInit () override
        {
-               wx_ptr<wxSplashScreen> splash;
+               wxSplashScreen* splash;
                try {
                        wxInitAllImageHandlers ();
 
index 2e28b548abb96b0e2b99e396f858c1c6ef4ca564..e2993f9f27ab163c449584d7bf0e5a7d03892b6c 100644 (file)
@@ -798,7 +798,7 @@ private:
 
        bool OnInit () override
        {
-               wx_ptr<wxSplashScreen> splash;
+               wxSplashScreen* splash;
 
                try {
                        wxInitAllImageHandlers ();
index 5ce02b1ea1d8e2e2f0b538dac0c20beb417b1c4e..ab018c44b9b60d18ee2d3608999fc1eafd194f05 100644 (file)
@@ -1171,7 +1171,7 @@ private:
 
        bool OnInit () override
        {
-               wx_ptr<wxSplashScreen> splash;
+               wxSplashScreen* splash;
                try {
                        wxInitAllImageHandlers ();
 
index 7a41f66e7cfa226c1bccb139f7fb88b3dc141082..f36bcdf25a3dfe86c6c52045419e3ed880ffea9c 100644 (file)
@@ -537,10 +537,10 @@ setup_audio_channels_choice (wxChoice* choice, int minimum)
 }
 
 
-wx_ptr<wxSplashScreen>
+wxSplashScreen*
 maybe_show_splash ()
 {
-       wx_ptr<wxSplashScreen> splash;
+       wxSplashScreen* splash;
 
        try {
                wxBitmap bitmap;
@@ -555,9 +555,9 @@ maybe_show_splash ()
                        }
 #ifdef DCPOMATIC_WINDOWS
                        /* Having wxSTAY_ON_TOP means error dialogues hide behind the splash screen on Windows, no matter what I try */
-                       splash.reset(bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, nullptr, -1, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE | wxFRAME_NO_TASKBAR);
+                       splash = new wxSplashScreen(bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, nullptr, -1, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE | wxFRAME_NO_TASKBAR);
 #else
-                       splash.reset(bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, nullptr, -1);
+                       splash = new wxSplashScreen(bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, nullptr, -1);
 #endif
                        wxYield ();
                }
index e18cfc5a78117584b7eb542bdb9f848a7a1a9d83..66b01640c5b1175583fee8898c5f7bc11335a88a 100644 (file)
@@ -119,7 +119,7 @@ extern wxString context_translation (wxString);
 extern std::string string_client_data (wxClientData* o);
 extern wxString time_to_timecode (dcpomatic::DCPTime t, double fps);
 extern void setup_audio_channels_choice (wxChoice* choice, int minimum);
-extern wx_ptr<wxSplashScreen> maybe_show_splash();
+extern wxSplashScreen* maybe_show_splash();
 extern double calculate_mark_interval (double start);
 extern bool display_progress (wxString title, wxString task);
 extern bool report_errors_from_last_job (wxWindow* parent);