Skip to content

Add support for using terminals with Containers and Executables - #173

Merged
Karol Zadora-Przylecki (karolz-ms) merged 38 commits into
mainfrom
dev/karolz/with-terminal
Jun 8, 2026
Merged

Add support for using terminals with Containers and Executables#173
Karol Zadora-Przylecki (karolz-ms) merged 38 commits into
mainfrom
dev/karolz/with-terminal

Conversation

@karolz-ms

Copy link
Copy Markdown
Collaborator

Sorry for the size... 😬

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment threadtest/integration/executable_controller_test.go
Comment threadinternal/termpty/conn_manager.go Outdated
// Socket file lifecycle is owned by the caller, not by ConnManager. Without
// this opt-out, net.UnixListener.Close() would unlink the path because Go
// created it via ListenUnix.
listener.SetUnlinkOnClose(false)

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.

The contract here puts UDS socket cleanup on the caller (SetUnlinkOnClose(false) + the comment block above), but no production caller actually unlinks the file. I grepped — os.Remove on the UDS path only happens in test helpers. Concretely, neither controllers/running_container_data.go closeTerminalResources nor internal/exerunners/process_executable_runner.go closeProcessRunResources/waitForConnManagerShutdown calls os.Remove(terminalSpec.UDSPath).

The consequences are user-visible: delete a terminal Executable/Container and recreate it with the same UDSPath and NewConnManager will fail with bind: address already in use → the resource goes to FailedToStart. The file also persists after DCP exits cleanly.

The natural place to fix this is in the cleanup paths after connMgr.Done() resolves — that's also why the executable runner's waitForConnManagerShutdown exists. (The container path doesn't even wait on Done() today; see the field comment on runningContainerData.connMgr which already claims it does.)

@karolz-msKarol Zadora-Przylecki (karolz-ms)May 29, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I am going to update that comment on the runningContainerData.connMgr member. But other than that, I am not sure what is the problem here. The contract is, DCP does not create the socket file, the client does, and that means DCP does not delete the socket file either.

And no, If a Container is deleted, and a new Container is created afterwards that uses the same socket path, the socket will be reused, there is no "address in use" problem becasue part of the old Container cleanup is closing the server connection to the socket.

Comment threadinternal/termpty/hmp1_server.go Outdated
Comment threadcontrollers/container_controller.go Outdated
Comment threadcontrollers/running_container_data.go
Comment threadpkg/process/concurrent_process_exit_handler.go Outdated
Comment threadpkg/process/process_util.go
Comment threadinternal/termpty/pty_linux.go
Comment threadinternal/docker/cli_orchestrator.go Outdated
Comment threadinternal/podman/cli_orchestrator.go Outdated
Comment threadinternal/docker/cli_orchestrator.go

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment threadinternal/termpty/pty_darwin.go
@danegsta

Copy link
Copy Markdown
Member

Conceptually, should we consider making the new pty controller be invoked via a child command rather than in the controller process directly? That'd be necessary to set us up for future support of persistent resources.

CopilotAI review requested due to automatic review settings May 29, 2026 23:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 74 out of 77 changed files in this pull request and generated 5 comments.

Files not reviewed (2)
  • api/v1/zz_generated.deepcopy.go: Language not supported
  • api/v1/zz_generated.model_name.go: Language not supported

Comment threadcontrollers/container_controller.go Outdated
Comment threadcontrollers/container_controller.go Outdated
Comment threadinternal/exerunners/process_executable_runner.go
Comment threadinternal/exerunners/process_executable_runner.go Outdated
Comment threadpkg/process/os_executor.go
CopilotAI review requested due to automatic review settings June 3, 2026 20:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 74 out of 77 changed files in this pull request and generated 5 comments.

Files not reviewed (2)
  • api/v1/zz_generated.deepcopy.go: Language not supported
  • api/v1/zz_generated.model_name.go: Language not supported

Comment threadtest/termchild/termchild_windows.go Outdated
Comment threadcontrollers/container_controller.go
Comment threadinternal/testutil/ctrlutil/test_container_orchestrator.go Outdated
Comment threadinternal/termpty/conn_manager.go Outdated
Comment threadAGENTS.md Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 3, 2026 20:15
CopilotAI reviewed Jun 3, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

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.

So the surprise change I springed on you around having DCP connect to the Terminal Host. I feel like I need to explain why that is necessary (and why we might not want a HMP1 listener in DCP at all).

One of the issues that we'll run into with terminal emulation is timing. Programs can send queries to the terminal emulator to determine settings like mouse support and other terminal capabilities. Sometimes these queries are time sensitive (if you don't get a response in N microseconds fallback to some undesirable compat mode). So to help mitigate that it makes more sense for DCP to first open the connection to the terminal host and make sure that the pathway is cleared before launching the process under DCP.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Roger. Currently the order of execution is, first start a process connected to a pseudoterminal, then make HMP1 connection to terminal host. I think it should be possible to do a focused change and introduce a new mode where this order is inverted. This should minimize the delay of the terminal host responding to program inquiries. Investigating...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

On related note, I am going to add another mode that has DCP own the terminal socket. David and I don't think the Aspire app host owning the socket will work for persistent Executables and Containers.

@karolz-msKarol Zadora-Przylecki (karolz-ms)Jun 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Thinking about it some more, I think I will just change the existing "listen" mode to have DCP own the socket file. So "listen" owns the socket file, and "connect" does not. But that will be a separate PR.

Comment threadAGENTS.md Outdated
Co-authored-by: David Negstad <50252651+danegsta@users.noreply.github.com>
@karolz-ms
Karol Zadora-Przylecki (karolz-ms) merged commit c650b2a into mainJun 8, 2026
11 checks passed
@karolz-ms
Karol Zadora-Przylecki (karolz-ms) deleted the dev/karolz/with-terminal branch June 8, 2026 23:46
@karolz-ms

Copy link
Copy Markdown
CollaboratorAuthor

/backport to release/0.25

@github-actions

Copy link
Copy Markdown

Started backporting to release/0.25: https://github.com/microsoft/dcp/actions/runs/27224217847

@github-actions

Copy link
Copy Markdown

Karol Zadora-Przylecki (@karolz-ms) backport PR couldn't be created automatically, please create the backport PR manually!

Open backport PR into release/0.25.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@karolz-ms@danegsta@mitchdenny