Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish multiplexer's inbound streams in more cases #483

Merged
merged 4 commits into from
Nov 15, 2024

Conversation

gjcairo
Copy link
Contributor

@gjcairo gjcairo commented Nov 14, 2024

Motivation

Currently, the multiplexer's inbound streams stream is finished only when the channel becomes inactive.
There are some scenarios in which the channel may be closed before it has a chance to become active, and the stream will never be finished. This can cause any users iterating over the stream to hang.

Modifications

This PR finishes the inbound streams stream when a connection error is fired, and when the handler is removed.

Result

Fewer bugs.

@gjcairo gjcairo added the semver/patch No public API change. label Nov 14, 2024
@gjcairo gjcairo force-pushed the multiplexer-finish-inbound-streams branch from a9113e2 to 92bb298 Compare November 14, 2024 15:24
Copy link
Contributor

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

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

Can we add a test for this too?

Comment on lines 217 to 222
for channel in self.streams.values {
channel.receiveStreamClosed(nil)
}

for channel in self._pendingStreams.values {
channel.receiveStreamClosed(nil)
}

self.streamChannelContinuation?.finish(throwing: error)
}

internal func propagateHandlerRemoved() {
for channel in self.streams.values {
channel.receiveStreamClosed(nil)
}

for channel in self._pendingStreams.values {
channel.receiveStreamClosed(nil)
}

self.streamChannelContinuation?.finish()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we should be closing the streams in these cases, we should just finish the continuation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For errorCaught I think you're right (although I'm not sure what it would mean if there was a connection error fired down the pipeline but we keep the streams opened?); however if the handler was removed, wouldn't it make sense to close the streams? Is there anything we can do with them if the connection has died?

Copy link
Contributor

Choose a reason for hiding this comment

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

In the HTTP2StreamMultiplexer, handler removed calls clearDidReadChannels in the common (i.e. this) multiplexer:

public func handlerRemoved(context: ChannelHandlerContext) {
self.context = nil
self.commonStreamMultiplexer.clearDidReadChannels()
}

I don't think we should have divergent behaviour between the two. When we reach handlerRemoved the streams will have already been closed.


For error caught, the HTTP2StreamMultiplexer only propagates stream errors to the child channels, they then get to decide how to act on those errors. Any connection level errors aren't propagated to streams and go down the channel pipeline and another handler decides how to act on it (usually by closing the connection, which will result in the streams being closed), but we should avoid short circuiting that because not all errors result in the connection being closed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks George, that's clear. I'll make the change.

Copy link
Contributor

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

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

One nit, but looks good otherwise, thanks @gjcairo

…ests.swift

Co-authored-by: George Barnett <gbarnett@apple.com>
@gjcairo gjcairo enabled auto-merge (squash) November 15, 2024 10:42
@gjcairo gjcairo merged commit 1879e72 into apple:main Nov 15, 2024
42 checks passed
@gjcairo gjcairo deleted the multiplexer-finish-inbound-streams branch November 15, 2024 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants