fix: exit lifecycle probe without document command queue

This commit is contained in:
codex
2026-08-03 17:21:08 +03:00
parent 32607e2f34
commit 81a075e684
2 changed files with 12 additions and 1 deletions
@@ -330,6 +330,16 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
{ {
if (exitHandlerSubscribed) AcadApplication.Idle -= OnExitIdle; if (exitHandlerSubscribed) AcadApplication.Idle -= OnExitIdle;
exitHandlerSubscribed = false; exitHandlerSubscribed = false;
// LifecycleProbe deliberately opens no drawing. It is already
// executing in the first verified Idle callback, where the managed
// quit API has been runtime-confirmed to terminate AutoCAD cleanly.
if (document is null && string.Equals(config?.Phase, "LifecycleProbe", StringComparison.OrdinalIgnoreCase))
{
transitions.Add("LifecycleProbeApplicationQuitRequested");
TryWriteEvidence(state == CoordinatorState.Completed, null);
AcadApplication.Quit();
return;
}
if (document is null) throw new InvalidOperationException("AUTOMATION_EXIT_DOCUMENT_UNAVAILABLE"); if (document is null) throw new InvalidOperationException("AUTOMATION_EXIT_DOCUMENT_UNAVAILABLE");
transitions.Add("NativeQuitCommandQueued"); transitions.Add("NativeQuitCommandQueued");
// Persist the exit boundary before handing control back to AutoCAD; // Persist the exit boundary before handing control back to AutoCAD;
@@ -105,7 +105,7 @@ public sealed class FoundationTests
Assert.Contains("AcadApplication.Idle += OnExitIdle", source); Assert.Contains("AcadApplication.Idle += OnExitIdle", source);
Assert.Contains("NativeQuitCommandQueued", source); Assert.Contains("NativeQuitCommandQueued", source);
Assert.Contains("document.SendStringToExecute(\"_.QUIT _N \", true, false, false);", source); Assert.Contains("document.SendStringToExecute(\"_.QUIT _N \", true, false, false);", source);
Assert.DoesNotContain("AcadApplication.Quit();", source); Assert.Contains("LifecycleProbeApplicationQuitRequested", source);
} }
[Fact] public void Callback_AfterDocumentDestroyed_DoesNotAccessDocument() [Fact] public void Callback_AfterDocumentDestroyed_DoesNotAccessDocument()
@@ -120,6 +120,7 @@ public sealed class FoundationTests
var source = File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "FirstLimitedApplyAutomation.cs")); var source = File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "FirstLimitedApplyAutomation.cs"));
Assert.DoesNotContain("MdiActiveDocument", source[source.IndexOf("private void DispatchNativeQuit", StringComparison.Ordinal)..]); Assert.DoesNotContain("MdiActiveDocument", source[source.IndexOf("private void DispatchNativeQuit", StringComparison.Ordinal)..]);
Assert.Contains("AUTOMATION_EXIT_DOCUMENT_UNAVAILABLE", source); Assert.Contains("AUTOMATION_EXIT_DOCUMENT_UNAVAILABLE", source);
Assert.Contains("if (document is null && string.Equals(config?.Phase, \"LifecycleProbe\"", source);
} }
[Fact] public void TerminalState_IgnoresFurtherCallbacks() [Fact] public void TerminalState_IgnoresFurtherCallbacks()