-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[camera]fix crash due to race condition in dispatch queue #4619
[camera]fix crash due to race condition in dispatch queue #4619
Conversation
6b9d636
to
b5dfe77
Compare
Yes, this is if anything an understatement. It was until recently very wrong, and some small steps to make it somewhat less wrong were taken, but it needs to be overhauled. |
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.
Could you merge in the latest version of master so that the tests run? A key recently expired, which I think is why everything is red.
packages/camera/camera/example/ios/RunnerTests/CameraDispatchQueueRaceConditionTests.m
Outdated
Show resolved
Hide resolved
packages/camera/camera/example/ios/RunnerTests/CameraDispatchQueueRaceConditionTests.m
Outdated
Show resolved
Hide resolved
@stuartmorgan thanks for the review. I think we are having code freeze until next year, so I will fix them next year when we come back. |
There's no code freeze for this repository (although people should make sure not to land publish-triggering changes unless they will be around to deal with any fallout, as is generally the case 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.
Thank for the fix! Left some comments.
packages/camera/camera/example/ios/RunnerTests/CameraDispatchQueueRaceConditionTests.m
Outdated
Show resolved
Hide resolved
packages/camera/camera/example/ios/RunnerTests/CameraDispatchQueueRaceConditionTests.m
Outdated
Show resolved
Hide resolved
@stuartmorgan gotcha. thanks for the clarification. I think I will wait till #4608 is landed, because I want to bump version and changelog in both PRs. |
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!
Is this obsoleted by your other changes, or should it be rebased and cleaned up for landing? |
will rebase and clean up |
d394cb5
to
d455f20
Compare
d455f20
to
d45d133
Compare
@stuartmorgan updated. PTAL. Thanks. |
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. Can you update this PR's description since this doesn't touch anything named _dispatchQueue
?
This PR fixed a crash due to race condition of
_captureSessionQueue
ivar. This kind of race condition is annoying and hard to fix because it takes tons of luck to reproduce (I accidentally touched iPhone's home bar, causing the app to become active and then immediately inactive, forming a race condition).Crash
Reproduce
(1) In sample app, start video recording then stop it.
(2) Swipe home bar just a bit on iPhone X, so the app becomes inactive and immediately regain active.
(3) Tap the video button again and observe this crash.
Root Cause
_captureSessionQueue
is checked in main thread, but set to nil in background thread, which is open to race condition:Explain
In the above reproduce step, (1) is to assign a new
_captureSessionQueue
, (2) is to trigger "dispose" and "create" method calls consecutively, resulting in a race condition, and (3) will pass in the_captureSessionQueue
which has been nil'ed out asynchronously by thedispose
call in previous step.Solution
(1) It looks like the camera plugin has pretty complicated threading logic and it's getting hard to maintain. There have been multiple related issues. If we get time I am interested in refactoring the threading model in the future.
(2) For now an easy fix to this race condition is not to nil out this
_captureSessionQueue
. DispatchQueues are quite lightweight as they are not actual threads.(3) Or we can dispatch to main thread again before setting nil, which should fix
_captureSessionQueue
race for this particular case, but may still open for other unknown casesIssues
flutter/flutter#96429
flutter/flutter#59124
flutter/flutter#52578 (comment)
Next Step
This PR should fix the crash, but we should start looking at simplifying the threading logic in this plugin. Ideally, a
DispatchQueue
should have its lifecycle scoped to the resource that the queue manages, instead of manually nil'ing out the reference. HOWEVER, let's step back a bit: should this even be a plugin problem?If we trace the execution from UI to plugin and back to UI, we get these thread hops:
The iOS platform thread is involved twice, just to dispatch to another thread, which means the whole process could have been as simple as:
I think engine should support invoking plugin methods in background. The benefits are:
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).