From 90fbf1770f0a1177a31c931196e3fe72b22c5bb6 Mon Sep 17 00:00:00 2001 From: Andrew <159703254+andrewsoonqn@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:07:34 +0800 Subject: [PATCH] Resolve duplicate agent ID conflicts Reject a printer-agent capability whose agent ID is already owned by another capability or built-in: flag the plugin error, disable the capability, and warn the user instead of silently ignoring it. --- src/slic3r/Utils/NetworkAgentFactory.cpp | 38 ++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/slic3r/Utils/NetworkAgentFactory.cpp b/src/slic3r/Utils/NetworkAgentFactory.cpp index 3883d99f2e..86f9cffadb 100644 --- a/src/slic3r/Utils/NetworkAgentFactory.cpp +++ b/src/slic3r/Utils/NetworkAgentFactory.cpp @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include namespace Slic3r { namespace { @@ -314,6 +316,21 @@ void NetworkAgentFactory::register_python_printer_agent(const std::string& plugi std::shared_ptr cached_agent; + auto reject_conflicting_capability = [plugin_key, capability_name](const std::string& error_message) { + if (!wxTheApp || GUI::wxGetApp().is_closing()) + return; + GUI::wxGetApp().CallAfter([plugin_key, capability_name, error_message]() { + if (GUI::wxGetApp().is_closing()) + return; + PluginManager& manager = PluginManager::instance(); + manager.set_plugin_error(plugin_key, error_message); + // note: the unload callback triggered by disabling will call deregister, + // which will be a no-op since the printer agent is never registered + manager.set_capability_enabled(plugin_key, capability_name, false); + wxMessageBox(wxString::FromUTF8(error_message.c_str()), _L("Plugins"), wxOK | wxICON_WARNING, GUI::wxGetApp().GetTopWindow()); + }); + }; + { std::lock_guard lock(s_registry_mutex); @@ -332,9 +349,10 @@ void NetworkAgentFactory::register_python_printer_agent(const std::string& plugi auto& python_agent_ids = get_python_printer_agent_ids(); for (const auto& pair : python_agent_ids) { if (pair.first != capability_key && pair.second == info.id) { - BOOST_LOG_TRIVIAL(warning) << "Printer-agent plugin '" << capability_name << "' uses duplicate agent ID '" << info.id - << "' already registered by capability '" << pair.first.second << "' from plugin '" - << pair.first.first << "'"; + const std::string error_message = "Printer-agent '" + info.name + "' could not be enabled: agent ID '" + info.id + + "' is already registered by capability '" + pair.first.second + "' from plugin '" + pair.first.first + "'."; + BOOST_LOG_TRIVIAL(warning) << error_message; + reject_conflicting_capability(error_message); return; } } @@ -354,12 +372,22 @@ void NetworkAgentFactory::register_python_printer_agent(const std::string& plugi auto& agents = get_printer_agents(); auto agent_it = agents.find(info.id); + // why: reject only when the ID is owned by SOMEONE ELSE - a built-in has an empty + // plugin_identifier, another plugin/capability has a different plugin_full_ref. When it + // IS the same plugin_full_ref, this capability is just re-registering itself, so fall + // through and refresh. if (agent_it != agents.end() && agent_it->second.plugin_identifier != plugin_full_ref) { - BOOST_LOG_TRIVIAL(warning) << "Printer-agent plugin '" << capability_name << "' uses agent ID '" << info.id - << "' already registered by '" << agent_it->second.display_name << "'"; + const std::string error_message = "Printer-agent '" + info.name + "' could not be enabled: agent ID '" + info.id + + "' is already registered by '" + agent_it->second.display_name + "'."; + BOOST_LOG_TRIVIAL(warning) << error_message; + reject_conflicting_capability(error_message); return; } + // why: insert_or_assign, not emplace - reaching here means the ID is new, or the same + // capability is re-registering (same plugin_full_ref). In the re-register case we WANT to + // overwrite so the factory closure points at the current live capability instance; emplace + // would silently keep the stale entry. agents.insert_or_assign(info.id, PrinterAgentInfo(info.id, info.name, plugin_full_ref, std::move(factory))); python_agent_ids[capability_key] = info.id;