2.2.0 pre4 (#84)

* Fix crash

* Update: Flutter 1223

* fix: networktestdialog crash

* Update Flutter 1223

* bump profile version to 02.02.42.02

* bump min_firm_ver to 1.0.0
This commit is contained in:
xiaoyeliu
2025-12-23 15:52:08 +08:00
committed by GitHub
parent 792f1e12f3
commit 4423dce212
20 changed files with 74934 additions and 75209 deletions

View File

@@ -1122,7 +1122,7 @@ GUI_App::GUI_App()
m_fltviews.set_app(this);
}
void GUI_App::shutdown()
void GUI_App::shutdown(bool isRecreate)
{
BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown enter";
@@ -1156,7 +1156,7 @@ void GUI_App::shutdown()
}
// Delete WebPresetDialog to ensure proper cleanup
if (SSWCP_MqttAgent_Instance::m_dialog != nullptr) {
if (SSWCP_MqttAgent_Instance::m_dialog != nullptr && !isRecreate) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": destroy WebPresetDialog");
delete SSWCP_MqttAgent_Instance::m_dialog;
SSWCP_MqttAgent_Instance::m_dialog = nullptr;
@@ -3614,7 +3614,8 @@ void GUI_App::recreate_GUI(const wxString &msg_name)
update_http_extra_header();
mainframe->shutdown();
mainframe->shutdown(true);
ProgressDialog dlg(msg_name, msg_name, 100, nullptr, wxPD_AUTO_HIDE);
dlg.Pulse();
dlg.Update(10, _L("Rebuild") + dots);

View File

@@ -416,7 +416,7 @@ private:
// Process command line parameters cached in this->init_params,
// load configs, STLs etc.
void post_init();
void shutdown();
void shutdown(bool isRecreate = false);
// If formatted for github, plaintext with OpenGL extensions enclosed into <details>.
// Otherwise HTML formatted for the system info dialog.
static std::string get_gl_info(bool for_github);

View File

@@ -889,7 +889,7 @@ void MainFrame::update_layout()
}
// Called when closing the application and when switching the application language.
void MainFrame::shutdown()
void MainFrame::shutdown(bool isRecreate)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter";
// BBS: backup
@@ -956,7 +956,7 @@ void MainFrame::shutdown()
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
wxGetApp().tabs_list.clear();
wxGetApp().model_tabs_list.clear();
wxGetApp().shutdown();
wxGetApp().shutdown(isRecreate);
// BBS: why clear ?
//wxGetApp().plater_ = nullptr;
@@ -2308,9 +2308,25 @@ static wxMenu* generate_help_menu()
});
append_menu_item(helpMenu, wxID_ANY, _L("Open Network Test"), _L("Open Network Test"), [](wxCommandEvent&) {
NetworkTestDialog dlg(wxGetApp().mainframe);
dlg.ShowModal();
});
// Use shared_ptr to manage dialog lifetime
auto dlg = std::make_shared<NetworkTestDialog>(wxGetApp().mainframe);
dlg->ShowModal();
// Keep dialog alive for 2 seconds after closing to allow background threads to finish
// Use a timer to delay the destruction
class DelayedReleaseTimer : public wxTimer {
std::shared_ptr<NetworkTestDialog> m_dialog;
public:
DelayedReleaseTimer(std::shared_ptr<NetworkTestDialog> dlg) : m_dialog(std::move(dlg)) {
StartOnce(5000); // 5 seconds delay
}
void Notify() override {
m_dialog.reset(); // Release the dialog
delete this; // Delete the timer itself
}
};
new DelayedReleaseTimer(dlg); // Timer will delete itself
});
// About
#ifndef __APPLE__

View File

@@ -246,7 +246,7 @@ public:
void update_layout();
// Called when closing the application and when switching the application language.
void shutdown();
void shutdown(bool isRecreate = false);
Plater* plater() { return m_plater; }

View File

@@ -293,6 +293,11 @@ NetworkTestDialog::~NetworkTestDialog()
m_closing.store(true);
m_download_cancel = true;
cleanup_threads();
// Small delay to allow any in-flight update_status calls to complete
// before destroying the shared_ptr control block
boost::this_thread::sleep_for(boost::chrono::milliseconds(50));
// Break the self-reference to avoid issues
self_ptr.reset();
}
@@ -1059,11 +1064,27 @@ void NetworkTestDialog::on_dpi_changed(const wxRect &suggested_rect)
void NetworkTestDialog::update_status(int job_id, wxString info)
{
// Early exit if dialog is closing - don't access any members
if (m_closing.load()) return;
auto evt = new wxCommandEvent(EVT_UPDATE_RESULT, this->GetId());
evt->SetString(info);
evt->SetInt(job_id);
wxQueueEvent(this, evt);
// Use try-catch to protect against accessing destroyed dialog
try {
// Double check before creating event
if (m_closing.load()) return;
auto evt = new wxCommandEvent(EVT_UPDATE_RESULT, this->GetId());
evt->SetString(info);
evt->SetInt(job_id);
// Triple check before queuing - race condition window is very small
if (!m_closing.load()) {
wxQueueEvent(this, evt);
} else {
delete evt;
}
} catch (...) {
// Silently ignore if dialog was destroyed during operation
}
}
void NetworkTestDialog::cleanup_threads()
@@ -1072,11 +1093,11 @@ void NetworkTestDialog::cleanup_threads()
for (int i = 0; i < TEST_JOB_MAX; i++) {
if (test_job[i] != nullptr) {
if (test_job[i]->joinable()) {
// Try to join with a short timeout (200ms)
// If thread is blocked in wxExecute, don't wait indefinitely
if (!test_job[i]->try_join_for(boost::chrono::milliseconds(200))) {
// Try to join with longer timeout (1000ms) to reduce chance of detach
// Threads should check m_closing and exit promptly
if (!test_job[i]->try_join_for(boost::chrono::milliseconds(1000))) {
// Thread didn't finish in time, detach it to avoid blocking
// The thread will check m_closing and exit safely
// The thread will check m_closing and should exit safely
test_job[i]->detach();
BOOST_LOG_TRIVIAL(warning) << "Thread " << i << " didn't finish in time, detached";
}
@@ -1089,8 +1110,8 @@ void NetworkTestDialog::cleanup_threads()
// Clean up sequence job thread
if (m_sequence_job != nullptr) {
if (m_sequence_job->joinable()) {
// Try to join with a short timeout (200ms)
if (!m_sequence_job->try_join_for(boost::chrono::milliseconds(200))) {
// Try to join with longer timeout (1000ms)
if (!m_sequence_job->try_join_for(boost::chrono::milliseconds(1000))) {
// Thread didn't finish in time, detach it
m_sequence_job->detach();
BOOST_LOG_TRIVIAL(warning) << "Sequence job thread didn't finish in time, detached";

View File

@@ -516,8 +516,28 @@ void SSWCP_Instance::sw_OpenNetworkDialog() {
finish_job();
wxGetApp().CallAfter([]() {
NetworkTestDialog dlg(wxGetApp().mainframe);
dlg.ShowModal();
// Use shared_ptr to manage dialog lifetime
auto dlg = std::make_shared<NetworkTestDialog>(wxGetApp().mainframe);
dlg->ShowModal();
// Keep dialog alive for 2 seconds after closing to allow background threads to finish
// Use a timer to delay the destruction
class DelayedReleaseTimer : public wxTimer
{
std::shared_ptr<NetworkTestDialog> m_dialog;
public:
DelayedReleaseTimer(std::shared_ptr<NetworkTestDialog> dlg) : m_dialog(std::move(dlg))
{
StartOnce(5000); // 5 seconds delay
}
void Notify() override
{
m_dialog.reset(); // Release the dialog
delete this; // Delete the timer itself
}
};
new DelayedReleaseTimer(dlg);
});
}
catch (std::exception& e) {