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
don't crash when Channel goes inactive in read triggered by write error #594
Conversation
var error: ChannelError { | ||
switch self { | ||
case .all: | ||
return .alreadyClosed | ||
return .ioOnClosedChannel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was just the wrong error here, .alreadyClosed
means close on previously closed channel. For all others, .ioOnClosedChannel
is right
1fc982b
to
30fce55
Compare
06c4eae
to
271b6fd
Compare
Sources/NIO/BaseSocketChannel.swift
Outdated
assert(self.lifecycleManager.isActive) | ||
pipeline.fireChannelReadComplete() | ||
if self.lifecycleManager.isActive { | ||
pipeline.fireChannelReadComplete() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No race here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is thread-safe.
I think a more important question is why we fire readComplete
more than once. I feel like we shouldn't be doing that: we should probably move the fireChannelReadComplete
outside the while
loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Lukasa I have no idea either why we're doing that but left it because it was that way. But let me just change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vlm thread-safety is fine here because we're on the Channel's event loop. So (unless we call out), the value of self.lifecycleManager.isActive
can't change. So if it's still active after readFromSocket
returns, it'll remain active until we return or call out again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Lukasa done
Motivation: Previously we asserted that a Channel cannot go inactive after calling out for a read that was triggered by (draining the receive buffer after) a write error. This assertion was put in place to guard against `readComplete` events sent on inactive channels. It did that job just fine but crashes aren't great so we now conditionally fire the `readComplete` event if the Channel stays active. Modifications: make the readComplete event firing conditional Result: fewer crashes, more happy faces
271b6fd
to
57eb1f4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
CI seriously unhappy: https://ci.swiftnio.io/job/swift-nio-master-410-prb/519/console
|
@tomerd ^^^ |
@swift-nio-bot test this please |
yea looks like ci broke, will look into it |
thanks @tomerd |
ugh, the ebs volume got detached. working to fix |
@swift-nio-bot test this please |
@weissi should be okay now, monitoring too |
awesome, thanks so much @tomerd |
also hit the confused kernel
which is #563 |
@swift-nio-bot test this please |
…or (#594) Motivation: Previously we asserted that a Channel cannot go inactive after calling out for a read that was triggered by (draining the receive buffer after) a write error. This assertion was put in place to guard against `readComplete` events sent on inactive channels. It did that job just fine but crashes aren't great so we now conditionally fire the `readComplete` event if the Channel stays active. Modifications: make the readComplete event firing conditional Result: fewer crashes, more happy faces Motivation: Explain here the context, and why you're making that change. What is the problem you're trying to solve. Modifications: Describe the modifications you've done. Result: After your change, what will change.
Motivation:
Previously we asserted that a Channel cannot go inactive after calling
out for a read that was triggered by (draining the receive buffer after)
a write error.
This assertion was put in place to guard against
readComplete
eventssent on inactive channels. It did that job just fine but crashes aren't
great so we now conditionally fire the
readComplete
event if theChannel stays active.
Modifications:
make the readComplete event firing conditional
Result:
fewer crashes, more happy faces