From c96de124b65f4e6771df156ca6e992359308c26c Mon Sep 17 00:00:00 2001 From: yztink Date: Sun, 20 Sep 2026 21:31:16 -0700 Subject: [PATCH] fix(plugin): prevent re-entrant plugin dispatch deadlock in execute_command --- src/app/commands/mod.rs | 15 ++++++++++----- src/app/plugin_host.rs | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index cc75d7fe1..f553fecc0 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -43,7 +43,12 @@ impl OpenCADStudio { } pub(super) fn dispatch_command(&mut self, cmd: &str) -> Task { - self.dispatch_command_inner(cmd, false) + self.dispatch_command_inner(cmd, false, false) + } + + /// Dispatch a command skipping external plugin dispatch to prevent reentrant deadlocks. + pub(super) fn dispatch_command_without_plugins(&mut self, cmd: &str) -> Task { + self.dispatch_command_inner(cmd, false, true) } /// Dispatch a verb typed at the interactive command line, falling back to @@ -55,10 +60,10 @@ impl OpenCADStudio { /// callers (ribbon, plugins, headless automation) use `dispatch_command` /// and never get silent substitution. pub(super) fn dispatch_command_or_suggest(&mut self, cmd: &str) -> Task { - self.dispatch_command_inner(cmd, true) + self.dispatch_command_inner(cmd, true, false) } - fn dispatch_command_inner(&mut self, cmd: &str, allow_suggest: bool) -> Task { + fn dispatch_command_inner(&mut self, cmd: &str, allow_suggest: bool, skip_plugins: bool) -> Task { let i = self.active_tab; // Expand a command alias ("L" → "LINE") on the leading token before any // routing, so every path below (Start-tab gate, plugins, all dispatch @@ -186,7 +191,7 @@ impl OpenCADStudio { return Task::none(); } - if crate::plugin::try_dispatch(self, i, cmd) { + if !skip_plugins && crate::plugin::try_dispatch(self, i, cmd) { // try_dispatch returns true for both finished commands and interactive // commands that it just installed. If no command is now active, the // tool was a one-shot and we must turn the ribbon highlight off here — @@ -225,7 +230,7 @@ impl OpenCADStudio { .next() { if !top.eq_ignore_ascii_case(cmd) { - return self.dispatch_command_inner(&top, false); + return self.dispatch_command_inner(&top, false, skip_plugins); } } } diff --git a/src/app/plugin_host.rs b/src/app/plugin_host.rs index 09c5cdd26..f50981609 100644 --- a/src/app/plugin_host.rs +++ b/src/app/plugin_host.rs @@ -432,7 +432,7 @@ impl<'a> HostSession<'a> { let cmd_name = parts[0]; let resolved = self.app.resolve_alias(cmd_name); let effective = resolved.as_deref().unwrap_or(cmd_name); - let _ = self.app.dispatch_command(effective); + let _ = self.app.dispatch_command_without_plugins(effective); } let mut paused = false;