Skip to content

Close both proxy endpoints to interrupt blocked writes - #513

Open
sylvesterkaczmarek wants to merge 2 commits into
openai:mainfrom
sylvesterkaczmarek:fix/close-both-proxy-endpoints
Open

sylvesterkaczmarek wants to merge 2 commits into
openai:mainfrom
sylvesterkaczmarek:fix/close-both-proxy-endpoints

Conversation

@sylvesterkaczmarek

Copy link
Copy Markdown

Problem

The fallback connection proxy closes only the remaining copy's source after the first copy ends. That copy can instead be blocked in a destination Write. Closing its source does not interrupt that write, so Connections can wait indefinitely after EOF or an I/O error.

Change

Close both endpoints before waiting for the remaining copy. This preserves the fallback path's close-on-first-completion behavior while interrupting both reads and writes. Keep the separate TCP half-close implementation unchanged.

The net.Conn contract specifies that Close unblocks pending reads and writes on that connection.

Validation

  • Broad non-hardware suite: 123 top-level tests and 100 subtests passed.
  • Proxy, UDP, and endpoint suites also passed with the race detector, including existing socket and half-close coverage.
  • Four deterministic blocked-write cases fail on unchanged production code. They cover both copy directions, clean EOF, preserved I/O errors, and closure of both endpoints.
  • New regressions use synthetic closable peers to control exactly when a destination blocks. Test cleanup releases both peers after a failing baseline run.
  • Changed-code lint reported zero issues; git diff --check passed.

Validated on macOS arm64. No VM or hardware/runtime integration under internal/tests was run. No public interface, dependency, retry, or half-close policy changes.

Reproduced against f101ade5d8fdcad5e9c346472698649e7107a715.

Signed-off-by: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com>
Comment thread internal/proxy/proxy.go
case err := <-leftErrCh:
recordErr(err)
recordErr(right.Close())
recordErr(left.Close())

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.

When SSH peer closes its channel normally, the SSH library acks the close before returning EOF. This additional close then returns io.EOF which would be recorded as proxy failure. This would result in caller logging and error for a normal disconnect. We should make sure we handle this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for catching this, @yzhuang-oai. Fixed in verified commit 2f47880: the fallback proxy now treats EOF from an already-closed SSH channel (including wrapped EOF) as normal shutdown, while preserving unrelated I/O and Close errors. New regressions cover both copy directions and confirm that the earlier code fails. The proxy race test and related command/endpoint tests pass; the TCP half-close path is unchanged.

Signed-off-by: Sylvester Kaczmarek <16242628+sylvesterkaczmarek@users.noreply.github.com>

This branch has not been deployed

No deployments
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