From 224ab603957a176dabeb6fdc5afeb183b3684cbe Mon Sep 17 00:00:00 2001 From: Cheng Date: Sun, 12 Nov 2023 09:43:19 +0000 Subject: [PATCH] layout bug due to failure to call layout. Sqlite3 crash due to premature call to shutdown. calls to layout very rarely have any obvious effect, but sometimes under odd and idiosyncratic circumstances they do. Called shutdown after the destroy was executed, but destroy does not immediately destroy the windows, thus does not immediately finalize all compiled sql statements and close all database connections. You have to wait for all the windows to be destroyed. Again, a rare crash except under certain special circumstances. --- src/ISqlite3.h | 17 +++++++++++------ src/app.cpp | 1 + src/display_wallet.cpp | 4 ++++ src/frame.cpp | 4 ++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ISqlite3.h b/src/ISqlite3.h index 4c31833..ba6529b 100644 --- a/src/ISqlite3.h +++ b/src/ISqlite3.h @@ -31,9 +31,10 @@ class Icompiled_sql { protected: - Icompiled_sql() = default; // needed for derived constructor + Icompiled_sql() {} //Has to exist, because derived objects will exist and need to create their base class public: - virtual ~Icompiled_sql() = default; // needed for derived destructor + virtual ~Icompiled_sql() { + } //Has to exist, because derived objects will exist and need to destroy their base class // Bind is used when writing stuff into the database. These objects should continue to exist until the write is finalized or reset. virtual void Isqlite3_bind( int, const std::span) = 0; // https://sqlite.org/c3ref/bind.html virtual void Isqlite3_bind(int, int) = 0; @@ -69,18 +70,22 @@ class ISqlite3 protected: ISqlite3() = default; // needed for derived constructor public: - virtual ~ISqlite3() = default; // needed for derived destructor + virtual ~ISqlite3() { + }; // needed for derived destructor virtual void exec(const char*) = 0; }; // Factory method to open a database and produce a shared object wrapping the database -ISqlite3* Sqlite3_open(const char*); +ISqlite3* Sqlite3_open(const char*); //The actual run time object is the derived class +//Which lives a symbol space that is kept separate from wxWidgets C++ space // Factory method to create a database and produce a shared object wrapping the database -ISqlite3* Sqlite3_create(const char*); +ISqlite3* Sqlite3_create(const char*);//The actual run time object is the derived class +//Which lives a symbol space that is kept separate from wxWidgets C++ space // Factory method to prepare a compiled sql statement -Icompiled_sql* sqlite3_prepare(ISqlite3*, const char *); +Icompiled_sql* sqlite3_prepare(ISqlite3*, const char *);//The actual run time object is the derived class +//Which lives a symbol space that is kept separate from wxWidgets C++ space void sqlite3_init(); extern "C" { diff --git a/src/app.cpp b/src/app.cpp index 5c12081..2c70b6e 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -197,5 +197,6 @@ void App::OnError(wxCommandEvent& event) int App::OnExit() { if (errorCode)wxLogDebug("%s", szError); m_Config.Flush(); + sqlite3_shutdown(); return 0; } diff --git a/src/display_wallet.cpp b/src/display_wallet.cpp index b1dbacf..fc937ed 100644 --- a/src/display_wallet.cpp +++ b/src/display_wallet.cpp @@ -81,6 +81,10 @@ struct display_wallet::cleanup { assert(sizer); } ~cleanup() { + sizer->Layout(); + // most of the time the layout command has no effect, but it has effect + // if adding a name longer than any of the existing names + // as when one adds the first name. auto desired_size = sizer->ComputeFittingClientSize(singletonFrame); dirty_area.IncTo(desired_size); //singletonFrame->SetMinClientSize(desired_size); diff --git a/src/frame.cpp b/src/frame.cpp index 4ae63cf..77fc8c9 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -294,7 +294,7 @@ Frame::Frame(const wxString& wxs) } void Frame::OnExit(wxCommandEvent& event) { - if (m_panel) { +if (m_panel) { m_panel->Close(true); m_panel = nullptr; } @@ -305,7 +305,6 @@ void Frame::OnClose(wxCloseEvent& event) { // This event gives you the opportunity to clean up anything that needs explicit cleanup, albeit if you have done your work right nothing should need explicit cleanup, // and to object to the closing in a "file not saved" type situation. // https://docs.wxwidgets.org/trunk/classwx_close_event.html - if (sqlite3_shutdown())wxMessageBox(wxT(R"|(Sqlite3 shutdown error)|"), wsz_error, wxICON_ERROR); DestroyChildren(); Destroy(); //Default handler will destroy the window. This is our handler for the user calling close, replacing the default handler. } @@ -580,4 +579,5 @@ Frame::~Frame() { wxMenuTracker::check_dynamic_menus_absent(); } singletonFrame = nullptr; + if (sqlite3_shutdown())wxMessageBox(wxT(R"|(Sqlite3 shutdown error)|"), wsz_error, wxICON_ERROR); }