Skip to content

[camera_android] Avoid thread race conditions when closing the camera. #9090

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

davidmartos96
Copy link
Contributor

Fixes the second race condition described on flutter/flutter#165092

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

cc @camsim99

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

@davidmartos96 davidmartos96 requested a review from camsim99 as a code owner April 15, 2025 21:35
@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

Copy link
Contributor

@camsim99 camsim99 left a comment

Choose a reason for hiding this comment

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

LGTM!

@camsim99 camsim99 requested a review from stuartmorgan-g April 15, 2025 22:02
Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

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

Per the bot comment, this would need tests.

@camsim99 please make sure to check for sufficient testing as part of code review.

Log.i(TAG, "closeCaptureSession");

captureSession.close();
captureSessionToClose.close();
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this fix the race condition? If I'm understanding correctly, the premise is that we are calling this method simultaneously from two different threads. If that's true, then this version will call close twice on the same session, which will almost certainly just replace a null pointer exception with state error exception.

If this class is trying to interact with the same objects from multiple threads at the same time, that needs to actually be fixed in some robust way (most likely either locking or cross-thread redispatch). Changing individual variable access is almost never the right way to handle threading issues, and that seems to apply here as well.

@davidmartos96
Copy link
Contributor Author

davidmartos96 commented May 7, 2025

@stuartmorgan-g Thank you for reviewing.

I also thought about it possibly being replaced by a State error from the SDK, but after implementing the fix on our production app with heavy camera usage, the NullPointerException that was filling up our Crashlytics events stopped appearing and it didn't get replaced by a different error.

I'm not really sure how to really test this, because of its threading nature. I agree a more thread safe implementation could be made. But the original idea of this PR was a simple way to stop obtaining the NullPointerException on the "legacy" camera_android package, which I assume will be replaced by the camerax one at some point in the future.

@stuartmorgan-g
Copy link
Contributor

I also thought about it possibly being replaced by a State error from the SDK, but after implementing the fix on our production app with heavy camera usage, the NullPointerException that was filling up our Crashlytics events stopped appearing and it didn't get replaced by a different error.

Apparently close is special-cased.

However, if close is being called on the wrong thread in some cases, I don't see how we have any guarantee that the close call couldn't be interleaved with other non-close calls on the main thread, so it still seems like this is papering over one symptom of a threading bug rather than fixing the threading bug. Do we have some guarantee that this case is unique?

I'm not really sure how to really test this, because of its threading nature.

It depends on what the fix ultimately is. For instance, if we fix it by ensuring that all access happens on a single thread, then it's testable by synthetically calling the offending callback from a different thread in a test, and ensuring that the (mock) camera object is still called on the main thread. We have tests like that in several plugins that receives callbacks on background threads.

I agree a more thread safe implementation could be made. But the original idea of this PR was a simple way to stop obtaining the NullPointerException

When we have evidence of a bug (a threading issue, in this case), the goal should be fixing the bug, rather than hiding the symptom that alerted us to the bug.

on the "legacy" camera_android package, which I assume will be replaced by the camerax one at some point in the future.

I'm not sure I follow. Is the argument that it doesn't matter if this is fixed correctly because the primary development focus is on the CameraX version? If this is issue is worth making, reviewing, and landing a PR for, then it matters enough for our usual development standards to apply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants