Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/frontend/src/content/docs/app-host/with-terminal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,16 @@ When a resource has more than one replica, choose which one to attach to with `a
Add a terminal to a resource only once. Calling `WithTerminal()` more than once on the same resource throws an exception.
</Aside>

## Terminal cleanup after a crash or forced stop

Each terminal host listens on a per-replica Unix domain socket under `~/.aspire/trmnl/` on Linux and macOS. Aspire cleans these sockets up automatically when a resource stops normally, but it's also resilient to less graceful endings:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually three sockets per replica (producer, consumer, and control), and the cleanup code removes all three. Could we use plural wording here? “a per-replica Unix domain socket” makes the cleanup model inaccurate.


- If the AppHost sends `SIGTERM` (for example, `docker stop` or a process manager shutting things down) or you interrupt it with `Ctrl+C`, the terminal host receives the signal, cancels its work, and unlinks its own socket before exiting.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C3 · unverifiable on the target branch (release/13.5).

If the AppHost sends SIGTERM … or you interrupt it with Ctrl+C, the terminal host receives the signal, cancels its work, and unlinks its own socket before exiting.

On microsoft/aspire release/13.5 (8ab6999) the terminal host has no SIGTERM/SIGINT handling — src/Aspire.TerminalHost/ contains no PosixSignal registration. This behavior was added by microsoft/aspire#19344 (milestone 13.6, base main): src/Aspire.TerminalHost/TerminalHostProcessRunner.cs (L45–89) registers SIGINT+SIGTERM and the first signal grants the host a bounded window to unlink its sockets. Accurate against main; absent on release/13.5.

- If the AppHost process itself crashes or is killed without giving its children a chance to shut down, each terminal host detects that its parent process is gone and exits on its own shortly after.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C4 · unverifiable on the target branch (release/13.5).

each terminal host detects that its parent process is gone and exits on its own shortly after.

No parent-process watchdog is wired into the terminal host on release/13.5. Added by microsoft/aspire#19344 (13.6): TerminalHostProcessRunner.cs (L23–27) starts ParentProcessWatchdog.Start(..., TerminalHostParentProcessId, ...), and src/Shared/ParentProcessWatchdog.cs (L9–63) cancels and force-exits (5 s grace, exit code 124) once the parent PID is no longer alive. Accurate against main; absent on release/13.5.

- On the next AppHost startup, a background sweep reclaims any sockets left behind by replicas whose owning process is confirmed gone—for example, after a machine reboot or an unclean shutdown. Sockets belonging to a process that might still be running (or that Aspire can't confirm has exited) are left alone.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C5 · unverifiable on the target branch (release/13.5).

a background sweep reclaims any sockets left behind by replicas whose owning process is confirmed gone … Sockets belonging to a process that might still be running (or that Aspire can't confirm has exited) are left alone.

There is no orphan-cleanup service on release/13.5. Added by microsoft/aspire#19344 (13.6): src/Aspire.Hosting/Lifecycle/TerminalHostOrphanCleanupService.cs — a BeforeStartEvent sweep (L61) that reclaims only confirmed-dead owners: ownerIsRunningcontinue (L365–367) and unableToInspectOwnercontinue with "leaving its artifacts in place" (L356–363), so only a confirmed-not-running owner reaches DeleteReplicaFiles (L374). The prose matches this implementation precisely. Accurate against main; absent on release/13.5.


You don't need to do anything to benefit from this—it runs automatically in run mode. It doesn't apply to publish mode, since publish never materializes terminal hosts or their sockets.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C6 · unverifiable on the target branch (release/13.5).

it runs automatically in run mode. It doesn't apply to publish mode, since publish never materializes terminal hosts or their sockets.

The cleanup service this sentence describes does not exist on release/13.5. On main (via microsoft/aspire#19344, 13.6) the sweep subscribes only when executionContext.IsRunMode (TerminalHostOrphanCleanupService.cs L57), so the run-mode-only framing is correct there. Accurate against main; the described cleanup is absent on release/13.5.


## View terminals in the dashboard

When a resource has `WithTerminal` applied, its **Console Logs** page in the [Aspire dashboard](/dashboard/overview/) gains a live terminal session alongside the usual console log stream. You can drive the running process directly in the browser without leaving the dashboard. For example, you can type commands, scroll the scrollback buffer, and switch between replicas. Each replica appears as its own entry (for example, `agent-r0`, `agent-r1`, `agent-r2`) with an independent session.
Expand Down
Loading