Stop a failed box open leaking its error into the zone - #320
Open
LahaLuhem wants to merge 3 commits into
Open
Conversation
_openBox removes its own entry in a finally, so anything left in _openingBoxes belongs to an open that is still running. Removing it there dropped that future's error unhandled and hid the open from the next caller.
A box closing after a later open already took its name would otherwise deregister the live one.
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.
Fixes #319.
When an
openBoxfails and you retry it right away, the retry's error arrives twice. Once at whoever awaited it, which is right, and once as an unhandled error in the zone, which isn't.What was going on
A failed open kicks off
newBox?.close().ignore()and doesn't wait for it.close()awaitskeystore.close()first, sounregisterBoxlands a microtask later, by which point the retry has already put its own future in_openingBoxes. The dead box then removes it, and nobody is left to handle that future's error.Traced with prints on the failing run:
That lines up with everything the issue reported: the first attempt is always clean, N attempts leak N-1, and a single microtask between the calls makes it disappear.
The change
eca28ffa701708unregisterBoxclearing_openingBoxes10a08ccThe second one is a deleted line.
_openBoxalready removes its own entry in afinally, on success and on failure alike, so anything still sitting in_openingBoxesbelongs to an open that is running right now. Clearing it there was never doing a useful job.The third is a sibling of the same problem. A box closing slowly could deregister a live box that took its name in the meantime. I could not get that one to misbehave in a test, since
keystore.close()is one microtask while a box open does real file work, so the ordering happens to land the right way. It is guarded rather than left to luck.Heads up: the third commit's guard also happens to cover #319 on its own, because it returns early in exactly the failed-open case. So the two are not independent fixes, they overlap.
Tests
Three added in
hive_impl_test.dart:Red before, green after
At
eca28ff, before the fix:At
a701708and after, both pass.The first commit is deliberately red so the bug is visible in history. CI builds the merge result rather than each commit, so the checks here should be green. Squash it into the second if you would rather not have a red commit in the log.
Checked with
dart analyze --fatal-infos,dart format --set-exit-if-changed, and 590 tests on the VM. Also ranbox_base_teston chrome/dart2js, since the third commit touches code shared with web.