From 2614ef7d630cf5d8c1adc7533441c7917b9fb4a8 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Fri, 17 Jul 2026 22:06:37 +0800 Subject: [PATCH] Defer speed-dial web commands off the webview callback stack --- src/slic3r/GUI/SpeedDialDialog.cpp | 14 ++++++++++++++ src/slic3r/GUI/SpeedDialDialog.hpp | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/slic3r/GUI/SpeedDialDialog.cpp b/src/slic3r/GUI/SpeedDialDialog.cpp index 3204f68d8f..09140b9868 100644 --- a/src/slic3r/GUI/SpeedDialDialog.cpp +++ b/src/slic3r/GUI/SpeedDialDialog.cpp @@ -55,6 +55,8 @@ SpeedDialWebDialog::SpeedDialWebDialog(wxWindow* parent) } } +SpeedDialWebDialog::~SpeedDialWebDialog() { m_alive->store(false, std::memory_order_release); } + void SpeedDialWebDialog::request_show() { if (IsShown()) { @@ -77,6 +79,18 @@ void SpeedDialWebDialog::on_script_message(const nlohmann::json& payload) if (handle_common_script_command(payload)) return; + // Defer command handling out of the webview script-message callback: GTK and macOS deliver + // it synchronously inside the native webview callback, and window work on that stack is the + // crash class fixed in b779a7bfed/f2ccbfc8b5 (see PluginsDialog::on_script_message). + // run_action puts a modal confirm on that stack, which is the same bug. + wxGetApp().CallAfter([this, alive = m_alive, payload]() { + if (alive->load(std::memory_order_acquire)) + handle_web_command(payload); + }); +} + +void SpeedDialWebDialog::handle_web_command(const nlohmann::json& payload) +{ const std::string command = payload.value("command", ""); if (command == "request_actions") { m_page_ready = true; diff --git a/src/slic3r/GUI/SpeedDialDialog.hpp b/src/slic3r/GUI/SpeedDialDialog.hpp index 7c5f8ac40b..52ee05e502 100644 --- a/src/slic3r/GUI/SpeedDialDialog.hpp +++ b/src/slic3r/GUI/SpeedDialDialog.hpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include namespace Slic3r { namespace GUI { @@ -11,15 +13,20 @@ class SpeedDialWebDialog : public WebViewHostDialog { public: explicit SpeedDialWebDialog(wxWindow* parent); + ~SpeedDialWebDialog() override; void request_show(); private: void on_script_message(const nlohmann::json& payload) override; + void handle_web_command(const nlohmann::json& payload); void resize_to_content(int height); void run_action(const std::string& id, const std::string& title); void send_actions(); bool m_page_ready{false}; + // Guards the CallAfter in on_script_message across dialog destruction, same as + // PluginsDialog::m_alive (PluginsDialog.hpp:249). + std::shared_ptr> m_alive = std::make_shared>(true); }; }}