fix(plugin): prevent re-entrant plugin dispatch deadlock in execute_command

This commit is contained in:
yztink committed 2026-09-20 21:31:16 -07:00
1 parent fbedb3736e
commit c96de124b6
2 files changed
+11 -6

No files matched your search

+10 -5
View File
@@ -43,7 +43,12 @@ impl OpenCADStudio {
}
pub(super) fn dispatch_command(&mut self, cmd: &str) -> Task<Message> {
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<Message> {
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<Message> {
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<Message> {
fn dispatch_command_inner(&mut self, cmd: &str, allow_suggest: bool, skip_plugins: bool) -> Task<Message> {
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);
}
}
}
+1 -1
View File
@@ -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;