-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Add stricter assertions regarding stream state. #812
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
Merged
wilhuff
merged 1 commit into
wilhuff/response-dispatch-queue
from
mikelehen/rework-stream-dispatching
Feb 19, 2018
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -263,12 +263,12 @@ - (void)startWithDelegate:(id)delegate { | |
|
||
/** Add an access token to our RPC, after obtaining one from the credentials provider. */ | ||
- (void)resumeStartWithToken:(FSTGetTokenResult *)token error:(NSError *)error { | ||
[self.workerDispatchQueue verifyIsCurrentQueue]; | ||
|
||
if (self.state == FSTStreamStateStopped) { | ||
// Streams can be stopped while waiting for authorization. | ||
return; | ||
} | ||
|
||
[self.workerDispatchQueue verifyIsCurrentQueue]; | ||
FSTAssert(self.state == FSTStreamStateAuth, @"State should still be auth (was %ld)", | ||
(long)self.state); | ||
|
||
|
@@ -525,11 +525,7 @@ - (void)handleStreamMessage:(id)value { | |
*/ | ||
- (void)handleStreamClose:(nullable NSError *)error { | ||
FSTLog(@"%@ %p close: %@", NSStringFromClass([self class]), (__bridge void *)self, error); | ||
|
||
if (![self isStarted]) { // The stream could have already been closed by the idle close timer. | ||
FSTLog(@"%@ Ignoring server close for already closed stream.", NSStringFromClass([self class])); | ||
return; | ||
} | ||
FSTAssert([self isStarted], @"handleStreamClose: called for non-started stream."); | ||
|
||
// In theory the stream could close cleanly, however, in our current model we never expect this | ||
// to happen because if we stop a stream ourselves, this callback will never be called. To | ||
|
@@ -550,11 +546,7 @@ - (void)handleStreamClose:(nullable NSError *)error { | |
*/ | ||
- (void)writeValue:(id)value __used { | ||
[self.workerDispatchQueue verifyIsCurrentQueue]; | ||
|
||
if (![self isStarted]) { | ||
FSTLog(@"%@ Ignoring stream message from inactive stream.", NSStringFromClass([self class])); | ||
return; | ||
} | ||
FSTAssert([self isStarted], @"writeValue: called for stopped stream."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In contrast to the above, this and below should be safe again because they're only called by gRPC. |
||
|
||
if (!self.messageReceived) { | ||
self.messageReceived = YES; | ||
|
@@ -587,6 +579,8 @@ - (void)writeValue:(id)value __used { | |
- (void)writesFinishedWithError:(nullable NSError *)error __used { | ||
error = [FSTDatastore firestoreErrorForError:error]; | ||
[self.workerDispatchQueue verifyIsCurrentQueue]; | ||
FSTAssert([self isStarted], @"writesFinishedWithError: called for stopped stream."); | ||
|
||
[self handleStreamClose:error]; | ||
} | ||
|
||
|
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.
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.
I don't think this is safe at all.
PR #811 was defending against gRPC calling us and enqueueing an error while (or just before) we were already processing a close for a different reason. This pushed the check in the callback filter out onto the dispatch queue making the callback filter effective again and prevents callbacks from gRPC from getting us after the stream is closed.
However, it's still the case that an idle close timer firing, a user disableNetwork, and a gRPC error can be enqueued at the same time. The first one to succeed may now prevent gRPC from kicking out any further events, but the subsequent close actions are still going to pass through 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.
Agree to disagree.
Whichever of those 3 are executed first will call
closeWithFinalState:
which will callsuppressCallbacks
in conjunction with settingstate
to a non-started value, which will prevent subsequent calls tohandleStreamClose:
.The only other caller of
handleStreamClose:
is resumeStartWithToken:
when handling auth failures, but it asserts thatself.state == FSTStreamStateAuth
immediately prior to callinghandleStreamClose:
so this assert is safe in that case too.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.
Said differently, we always suppress callbacks when setting the stream state to a non started state... And with your change we can now rely on that to prevent any subsequent handleStreamClose calls.
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.
Okay, I've convinced myself you're right by tracing it through. All callers check the state prior to calling so this is safe.