Skip to content

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

Conversation

mikelehen
Copy link
Contributor

In the interest of going for the PRs-based-on-PRs world record, I additionally would like to replace some of our race condition leniency with stricter asserts. I've traced the call sites for each assert and feel pretty confident that they should be safe now.

FSTLog(@"%@ Ignoring server close for already closed stream.", NSStringFromClass([self class]));
return;
}
FSTAssert([self isStarted], @"handleStreamClose: called for non-started stream.");
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 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.

Copy link
Contributor Author

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 call suppressCallbacks in conjunction with setting state to a non-started value, which will prevent subsequent calls to handleStreamClose:.

The only other caller of handleStreamClose: is resumeStartWithToken: when handling auth failures, but it asserts that self.state == FSTStreamStateAuth immediately prior to calling handleStreamClose: so this assert is safe in that case too.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

FSTLog(@"%@ Ignoring stream message from inactive stream.", NSStringFromClass([self class]));
return;
}
FSTAssert([self isStarted], @"writeValue: called for stopped stream.");
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

@wilhuff wilhuff left a comment

Choose a reason for hiding this comment

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

LGTM

FSTLog(@"%@ Ignoring server close for already closed stream.", NSStringFromClass([self class]));
return;
}
FSTAssert([self isStarted], @"handleStreamClose: called for non-started stream.");
Copy link
Contributor

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.

@wilhuff wilhuff merged commit b78f906 into wilhuff/response-dispatch-queue Feb 19, 2018
@wilhuff wilhuff deleted the mikelehen/rework-stream-dispatching branch February 19, 2018 19:36
mikelehen pushed a commit that referenced this pull request Feb 20, 2018
* Use -[GRPCCall setResponseDispatchQueue] to dispatch GRPC callbacks directly onto the Firestore worker queue. This saves a double-dispatch and simplifies our logic.
* Add stricter assertions regarding stream state. (#812)
@firebase firebase locked and limited conversation to collaborators Nov 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants