Repository navigation
Raise EOFError when the connection closes while a write waits - #42
Open
andrewfader wants to merge 1 commit into
Open
andrewfader wants to merge 1 commit into
andrewfader wants to merge 1 commit into
Conversation
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
write_frameandwrite_framesread@frameragain after taking the write lock, andwrite_framenever checks it at all. Under async-http the lock is a semaphore and the write inside it can block on the socket, so the reading task can close the connection (setting@framer = nil) while a writer waits. The writer then raisesNoMethodErroron nil instead of theEOFErrora closed connection gives, and async-http doesn't retryNoMethodError.We hit both traces in production with Falcon and async-http talking HTTP/2 to a CDN-fronted origin:
undefined method 'flush' for nilfrom #41's shape (peer hangs up while a request waits on the lock), andundefined method 'write_frame' for nilfrom socketry/async-http#254 (a window update after a graceful GOAWAY closed the connection).The fix checks the framer at each use, inside the lock and again before the flush, raising
EOFError, "Connection closed!"aswrite_framesalready does for a connection that was closed up front.The new tests close the connection from inside
synchronize, which is the state the race leaves behind. Without the change they fail withNoMethodError: undefined method 'write_frame' for nilandundefined method 'flush' for nil; with it both raiseEOFError. The reproduction script in #41 now ends withEOFErrorfrom the GET.bundle exec sus(248 passed) andbundle exec rubocopare clean.This turns #254 into an
EOFErrorbut doesn't make the buffered body readable; that part is in async-http, where a closed stream shouldn't request a window update at all.Fixes #41.