mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-27 12:52:07 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user