Skip to content

tailcat_ssh: avoid PTY session hang on slow/interactive shells - #8

Open
awdemos wants to merge 1 commit into
tailscale:mainfrom
awdemos:fix-ssh-pty-hang
Open

tailcat_ssh: avoid PTY session hang on slow/interactive shells#8
awdemos wants to merge 1 commit into
tailscale:mainfrom
awdemos:fix-ssh-pty-hang

Conversation

@awdemos

@awdemos awdemos commented Aug 27, 2026

Copy link
Copy Markdown

runWithPTY previously blocked on io.Copy(sess, ptmx) before calling cmd.Wait(). If the shell did not exit immediately, the function would never reach cmd.Wait(), and the deferred ptmx.Close never ran. This could hang the whole SSH session.

Restructure the PTY path so cmd.Wait() and the stdout copy run concurrently. When the command exits first, cancel the window-resize goroutine and drain the remaining stdout. When the client disconnects first, kill the shell and wait for it to exit.

Also close the pty slave fd after cmd.Start and set tty=nil so the deferred cleanup does not double-close it.

runWithPTY previously blocked on io.Copy(sess, ptmx) before calling
cmd.Wait(). If the shell did not exit immediately, the function would
never reach cmd.Wait(), and the deferred ptmx.Close never ran. This
could hang the whole SSH session.

Restructure the PTY path so cmd.Wait() and the stdout copy run
concurrently. When the command exits first, cancel the window-resize
goroutine and drain the remaining stdout. When the client disconnects
first, kill the shell and wait for it to exit.

Also close the pty slave fd after cmd.Start and set tty=nil so the
deferred cleanup does not double-close it.

Updates tailscale/tailcat (adversarial audit).
@bradfitz

Copy link
Copy Markdown
Member

Please file an issue first demonstrating the problem.

And this change will need a test update that failed before the change and passes after the change.

@awdemos

awdemos commented Aug 28, 2026

Copy link
Copy Markdown
Author

Please file an issue first demonstrating the problem.

And this change will need a test update that failed before the change and passes after the change.

whoa bradfitz! I haven't worked with you since Six Apart! Good to see you I'll get to this shortly.

Sign up for free to 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.

2 participants