Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix a newcoming child being sometimes ignored
The failure went like this: * A child arrives. * In the meantime, the parent enters `tryMakeCompletingSlowPath` and remembers the current list of handlers, which is an empty or a single-element one. * The parent updates the state to the finishing one. * The child enters the list. * The parent traverses *an old list*, the one from before the child arrived. It sees no children in the empty/single-element list and forgets about the child. Why, then, was it that this worked before? It was because there was a guarantee that no new children are going to be registered if two conditions are true: * The root cause of the error is set to something, * And the state is already "completing". `tryMakeCompletingSlowPath` sets the state to completing, and because it updates the state inside `synchronized`, there was a guarantee that the child would see either the old state (and, if it adds itself successfully, then `tryMakeCompletingSlowPath` will retry) or the complete new one, with `isCompleting` and the error set to something. Additionally, `tryMakeCompletingSlowPath` is entered for empty or single-element lists *almost only* when it's completing with an error, so in effect, it was *almost always* guaranteed that new children weren't going to be registered. An exception is a tiny bug that used to be present, but wasn't noticed by anyone because of how incredibly specific it was: `tryMakeCompletingSlowPath` can also be entered for single-element lists when completing without an error if that single element is not a child. In this case, in extremely rare racy scenarios, attaching a child could result in the child registering itself, but the parent forgetting to wait for it.
- Loading branch information