fix: crash on windows

This commit is contained in:
peachismomo
2026-08-06 06:08:02 +08:00
parent acb0be6ed9
commit ef4815b26c
4 changed files with 67 additions and 14 deletions

View File

@@ -1110,6 +1110,8 @@ void MainFrame::update_edge_panels()
void MainFrame::shutdown()
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "MainFrame::shutdown enter";
if (m_project != nullptr)
m_project->shutdown();
m_plugin_pages.shutdown();
#ifdef __WXGTK__
// Edge panels are child windows — wxWidgets destroys them automatically.

View File

@@ -74,7 +74,18 @@ ProjectPanel::ProjectPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos,
Fit();
}
ProjectPanel::~ProjectPanel() {}
ProjectPanel::~ProjectPanel()
{
shutdown();
}
void ProjectPanel::shutdown()
{
m_reload_cancel_token->store(true, std::memory_order_release);
if (m_reload_task && m_reload_task->joinable())
m_reload_task->join();
m_reload_task.reset();
}
// Helper to convert newlines to <br>
static std::string convert_newlines_to_br(const std::string& text) {
@@ -101,7 +112,17 @@ void ProjectPanel::onWebNavigating(wxWebViewEvent& evt)
void ProjectPanel::on_reload(wxCommandEvent& evt)
{
boost::thread reload = boost::thread([this] {
if (wxTheApp == nullptr || wxGetApp().is_closing() ||
m_reload_cancel_token->load(std::memory_order_acquire))
return;
if (m_reload_task && m_reload_task->joinable())
m_reload_task->join();
const auto cancel_token = m_reload_cancel_token;
m_reload_task = std::make_unique<boost::thread>([this, cancel_token] {
if (cancel_token->load(std::memory_order_acquire) || wxTheApp == nullptr || wxGetApp().is_closing())
return;
std::string update_type;
std::string license;
std::string model_name;
@@ -115,6 +136,9 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
std::map<std::string, std::vector<json>> files;
if (wxGetApp().plater() == nullptr)
return;
Model model = wxGetApp().plater()->model();
auto model_info = model.model_info;
@@ -156,7 +180,14 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
std::string file_path = encode_path(wxGetApp().plater()->model().get_auxiliary_file_temp_path().c_str());
if (!file_path.empty()) {
files = Reload(file_path);
wxGetApp().CallAfter([this, file_path, files] { m_auxiliary->Reload(file_path, files); });
if (cancel_token->load(std::memory_order_acquire) || wxTheApp == nullptr || wxGetApp().is_closing())
return;
wxGetApp().CallAfter([this, cancel_token, file_path, files] {
if (cancel_token->load(std::memory_order_acquire) || wxTheApp == nullptr || wxGetApp().is_closing())
return;
m_auxiliary->Reload(file_path, files);
});
} else {
clear_model_info();
return;
@@ -215,15 +246,18 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
json m_Res = json::object();
m_Res["command"] = "show_3mf_info";
m_Res["sequence_id"] = std::to_string(ProjectPanel::m_sequence_id++);
m_Res["sequence_id"] = std::to_string(ProjectPanel::m_sequence_id.fetch_add(1, std::memory_order_relaxed));
m_Res["model"] = j;
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', false, json::error_handler_t::ignore));
if (m_web_init_completed) {
wxGetApp().CallAfter([this, strJS] {
if (m_web_init_completed.load(std::memory_order_acquire) &&
!cancel_token->load(std::memory_order_acquire) && wxTheApp != nullptr && !wxGetApp().is_closing()) {
wxGetApp().CallAfter([this, cancel_token, strJS] {
if (cancel_token->load(std::memory_order_acquire) || wxTheApp == nullptr || wxGetApp().is_closing())
return;
RunScript(strJS.ToStdString());
});
});
}
});
}
@@ -264,7 +298,7 @@ void ProjectPanel::OnScriptMessage(wxWebViewEvent& evt)
}
}
else if (strCmd == "request_3mf_info") {
m_web_init_completed = true;
m_web_init_completed.store(true, std::memory_order_release);
}
else if (strCmd == "edit_project_info") {
show_info_editor(true);
@@ -307,13 +341,20 @@ void ProjectPanel::update_model_data()
void ProjectPanel::clear_model_info()
{
if (wxTheApp == nullptr || wxGetApp().is_closing() ||
m_reload_cancel_token->load(std::memory_order_acquire))
return;
json m_Res = json::object();
m_Res["command"] = "clear_3mf_info";
m_Res["sequence_id"] = std::to_string(ProjectPanel::m_sequence_id++);
m_Res["sequence_id"] = std::to_string(ProjectPanel::m_sequence_id.fetch_add(1, std::memory_order_relaxed));
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', false, json::error_handler_t::ignore));
wxGetApp().CallAfter([this, strJS] {
const auto cancel_token = m_reload_cancel_token;
wxGetApp().CallAfter([this, cancel_token, strJS] {
if (cancel_token->load(std::memory_order_acquire) || wxTheApp == nullptr || wxGetApp().is_closing())
return;
RunScript(strJS.ToStdString());
});
}

View File

@@ -26,9 +26,11 @@
#include "nlohmann/json.hpp"
#include "slic3r/Utils/json_diff.hpp"
#include <atomic>
#include <map>
#include <vector>
#include <memory>
#include <boost/thread.hpp>
#include "Event.hpp"
#include "libslic3r/ProjectTask.hpp"
#include "wxExtensions.hpp"
@@ -60,14 +62,17 @@ struct project_file{
class ProjectPanel : public wxPanel
{
private:
bool m_web_init_completed = {false};
std::atomic<bool> m_web_init_completed{false};
bool m_reload_already = {false};
std::shared_ptr<std::atomic<bool>> m_reload_cancel_token{std::make_shared<std::atomic<bool>>(false)};
std::unique_ptr<boost::thread> m_reload_task;
wxWebView* m_browser = {nullptr};
AuxiliaryPanel* m_auxiliary{nullptr};
wxString m_project_home_url;
wxString m_root_dir;
static inline int m_sequence_id = 8000;
static inline std::atomic<int> m_sequence_id{8000};
void show_info_editor(bool show);
@@ -75,6 +80,7 @@ private:
public:
ProjectPanel(wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~ProjectPanel();
void shutdown();
void onWebNavigating(wxWebViewEvent& evt);

View File

@@ -8477,8 +8477,12 @@ void Page::activate(ConfigOptionMode mode, std::function<void()> throw_if_cancel
#ifdef __WXMSW__
// BBS: fix field control position
wxTheApp->CallAfter([this]() {
for (auto group : m_optgroups) {
wxTheApp->CallAfter([wp = std::weak_ptr<Page>(shared_from_this())]() {
auto page = wp.lock();
if (!page)
return;
for (auto group : page->m_optgroups) {
if (group->custom_ctrl)
group->custom_ctrl->fixup_items_positions();
}