From 46b3871f8df1c1a1a81ef71e7360e225ed6ef34f Mon Sep 17 00:00:00 2001 From: Ian Chua Date: Wed, 14 Oct 2026 13:19:04 +0800 Subject: [PATCH] fix: login crash when network plugin is unavailable (#16438) * fix: login crash when network plugin is unavailable * fix: directly use !config_version.empty() for the control block * Use if/else for the empty plug-in version check * Fix multi-device task list using a deleted network agent after plug-in reload --------- Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com> Co-authored-by: SoftFever --- src/slic3r/GUI/GUI_App.cpp | 120 ++++++++++++++++----------------- src/slic3r/GUI/TaskManager.cpp | 17 +++-- src/slic3r/GUI/TaskManager.hpp | 6 +- 3 files changed, 76 insertions(+), 67 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 67d085f888..fa8bc811c3 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3916,81 +3916,74 @@ bool GUI_App::on_init_network(bool try_backup) if (config_version.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": no version configured, need to download"; m_networking_need_update = true; + } else { + int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); + __retry: + if (!load_agent_dll) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll ok"; - if (!m_device_manager) - m_device_manager = new Slic3r::DeviceManager(); - if (!m_user_manager) - m_user_manager = new Slic3r::UserManager(); - - return false; - } - - int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); - __retry: - if (!load_agent_dll) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll ok"; - - std::string loaded_version = Slic3r::NetworkAgent::get_version(); - if (app_config && !loaded_version.empty() && loaded_version != "00.00.00.00") { - // Self-heal only when a genuinely different series loaded than configured (e.g. the - // configured build was unavailable and a fallback loaded). Within a series the - // loaded build (02.08.01.53) differs from the series config (02.08.01) by design, so - // compare series, not the raw string, and store the managed series form - a custom - // config (02.08.01_custom) keeps its own name. - std::string config_version = app_config->get_network_plugin_version(); - std::string loaded_series = network_plugin_series(loaded_version); - if (network_plugin_series(config_version) != loaded_series) { - std::string synced = is_series_managed_version(loaded_version) ? loaded_series : loaded_version; - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": syncing config version from " << config_version - << " to loaded " << loaded_version << " (stored as " << synced << ")"; - app_config->set_network_plugin_version(synced); - app_config->save(); + std::string loaded_version = Slic3r::NetworkAgent::get_version(); + if (app_config && !loaded_version.empty() && loaded_version != "00.00.00.00") { + // Self-heal only when a genuinely different series loaded than configured (e.g. the + // configured build was unavailable and a fallback loaded). Within a series the + // loaded build (02.08.01.53) differs from the series config (02.08.01) by design, so + // compare series, not the raw string, and store the managed series form - a custom + // config (02.08.01_custom) keeps its own name. + std::string config_version = app_config->get_network_plugin_version(); + std::string loaded_series = network_plugin_series(loaded_version); + if (network_plugin_series(config_version) != loaded_series) { + std::string synced = is_series_managed_version(loaded_version) ? loaded_series : loaded_version; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": syncing config version from " << config_version + << " to loaded " << loaded_version << " (stored as " << synced << ")"; + app_config->set_network_plugin_version(synced); + app_config->save(); + } } - } - if (check_networking_version()) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, compatibility version"; - auto bambu_source = Slic3r::NetworkAgent::get_bambu_source_entry(); - if (!bambu_source) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": can not get bambu source module!"; - m_networking_compatible = false; + if (check_networking_version()) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, compatibility version"; + auto bambu_source = Slic3r::NetworkAgent::get_bambu_source_entry(); + if (!bambu_source) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": can not get bambu source module!"; + m_networking_compatible = false; + if (should_load_networking_plugin) { + m_networking_need_update = true; + } + } + } else { + if (try_backup) { + int result = Slic3r::NetworkAgent::unload_network_module(); + BOOST_LOG_TRIVIAL(info) << "on_init_network, version mismatch, unload_network_module, result = " << result; + load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(true, config_version); + try_backup = false; + goto __retry; + } + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, version dismatch, need upload network module"; if (should_load_networking_plugin) { m_networking_need_update = true; } } } else { - if (try_backup) { - int result = Slic3r::NetworkAgent::unload_network_module(); - BOOST_LOG_TRIVIAL(info) << "on_init_network, version mismatch, unload_network_module, result = " << result; - load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(true, config_version); - try_backup = false; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll failed"; + // A failed install can leave the config naming a build that never made it to disk; + // fall back to the installed latest instead of dropping the user into the re-download + // flow. Only when the configured library is genuinely absent, though - a pinned series + // that is on disk but failed to load once must keep its pin, not be rewritten for good. + std::string latest = get_latest_network_version(); + if (config_version != latest && !BBLNetworkPlugin::versioned_library_exists(config_version) + && BBLNetworkPlugin::versioned_library_exists(latest)) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": falling back to installed " << latest; + config_version = latest; + app_config->set_network_plugin_version(latest); + app_config->save(); + load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); goto __retry; } - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, version dismatch, need upload network module"; if (should_load_networking_plugin) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, need upload network module"; m_networking_need_update = true; } } - } else { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll failed"; - // A failed install can leave the config naming a build that never made it to disk; - // fall back to the installed latest instead of dropping the user into the re-download - // flow. Only when the configured library is genuinely absent, though - a pinned series - // that is on disk but failed to load once must keep its pin, not be rewritten for good. - std::string latest = get_latest_network_version(); - if (config_version != latest && !BBLNetworkPlugin::versioned_library_exists(config_version) - && BBLNetworkPlugin::versioned_library_exists(latest)) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": falling back to installed " << latest; - config_version = latest; - app_config->set_network_plugin_version(latest); - app_config->save(); - load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(false, config_version); - goto __retry; - } - if (should_load_networking_plugin) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, need upload network module"; - m_networking_need_update = true; - } } } @@ -4018,6 +4011,11 @@ bool GUI_App::on_init_network(bool try_backup) else m_user_manager->set_agent(m_agent); + // A hot reload deletes the agent the task manager was built with. It lives until restart, so repoint it + // even if multi-device has since been turned off. + if (m_task_manager) + m_task_manager->set_agent(m_agent); + if (this->is_enable_multi_machine()) { if (!m_task_manager) { m_task_manager = new Slic3r::TaskManager(m_agent); diff --git a/src/slic3r/GUI/TaskManager.cpp b/src/slic3r/GUI/TaskManager.cpp index 712bfea67e..54efafe8ae 100644 --- a/src/slic3r/GUI/TaskManager.cpp +++ b/src/slic3r/GUI/TaskManager.cpp @@ -171,6 +171,11 @@ TaskManager::TaskManager(NetworkAgent* agent) ; } +void TaskManager::set_agent(NetworkAgent* agent) +{ + m_agent = agent; +} + int TaskManager::start_print(const std::vector& params, TaskSettings* settings) { @@ -240,17 +245,18 @@ int TaskManager::schedule(TaskStateInfo* task) fire_lifecycle_event(LifecycleEvent::PrintJobStarted, start_ctx); int result = -1; - if (!m_agent) { + NetworkAgent* agent = m_agent; + if (!agent) { BOOST_LOG_TRIVIAL(trace) << "task_manager: NetworkAgent is nullptr"; } else { - assert(m_agent); + assert(agent); try { // DEBUG FOR TEST #if 0 result = start_print_test(task->get_params(), task->update_status_fn, task->cancel_fn, task->wait_fn); #else - result = m_agent->start_print(task->get_params(), task->update_status_fn, task->cancel_fn, task->wait_fn); + result = agent->start_print(task->get_params(), task->update_status_fn, task->cancel_fn, task->wait_fn); #endif } catch (const std::exception& ex) { BOOST_LOG_TRIVIAL(error) << "task_manager: start_print threw: " << ex.what(); @@ -363,12 +369,13 @@ std::map TaskManager::get_local_task_list() std::map TaskManager::get_task_list(int curr_page, int page_count, int& total) { std::map out; - if (m_agent) { + NetworkAgent* agent = m_agent; + if (agent) { TaskQueryParams task_query_params; task_query_params.limit = page_count; task_query_params.offset = curr_page * page_count; std::string task_info; - int result = m_agent->get_user_tasks(task_query_params, &task_info); + int result = agent->get_user_tasks(task_query_params, &task_info); BOOST_LOG_TRIVIAL(trace) << "task_manager: get_task_list task_info=" << task_info; if (result == 0) { try { diff --git a/src/slic3r/GUI/TaskManager.hpp b/src/slic3r/GUI/TaskManager.hpp index 0f9686294d..66de945075 100644 --- a/src/slic3r/GUI/TaskManager.hpp +++ b/src/slic3r/GUI/TaskManager.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -158,6 +159,8 @@ public: static int SendingInterval; TaskManager(NetworkAgent* agent); + void set_agent(NetworkAgent* agent); + int start_print(const std::vector& params, TaskSettings* settings = nullptr); static void set_max_send_at_same_time(int count); @@ -184,7 +187,8 @@ private: std::vector m_sending_thread_list; std::mutex m_scedule_mutex; bool m_started { false }; - NetworkAgent* m_agent { nullptr }; + // Replaced on the main thread whenever networking is re-initialised, read by the sending threads. + std::atomic m_agent { nullptr }; std::chrono::system_clock::time_point last_sent_timestamp; };