Skip to content

Conversation

@Michaelgathara
Copy link

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Motivation and Context

This fixed issue #923

I fixed a race condition in ConnectHandler.swift where an asynchronous network connection could complete after the handler had already been removed from the pipeline.

This:

  • Added a removed flag to track if the handler is still active.
  • Updated the connection callback to check this flag; if the handler was removed while connecting, we now immediately close the new connection instead of trying to use it.

This prevents the EXC_BREAKPOINT crash in container-runtime-linux that occurred when kinc (Kubernetes in Container) created rapid connections. As we saw in the issue attached

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

@jglogan
Copy link
Contributor

jglogan commented Dec 5, 2025

@Michaelgathara Thanks! Could you set up commit signing and update your PR with signed commits?

See: https://github.com/apple/containerization/blob/main/CONTRIBUTING.md#pull-requests

@Michaelgathara
Copy link
Author

@Michaelgathara Thanks! Could you set up commit signing and update your PR with signed commits?

See: https://github.com/apple/containerization/blob/main/CONTRIBUTING.md#pull-requests

Hi, sorry for missing that. Should be fixed now!

.connect(to: serverAddress)
.assumeIsolatedUnsafeUnchecked()
.whenComplete { result in
guard !self.removed else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain the race a little more clearly? The sequence of events I think you're trying to guard against is:

  1. channelActive event, ConnectHandler will be in the handler chain, this method gets called, and this block runs when the backend connection completes
  2. this handler gets removed from the chain via removeHandler()
  3. the backend connection setup completes successfully, and we call glue() to replace ConnectHandler with GlueHandler.

How does step 2 come about? The only way that I see removeHandler() getting called and self.removed being set to true is from glue(), which only happens if execution has proceeded past your check.

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