-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[shared_preferences] Fix concurrent modification of the shared preferences on Android #3684
Conversation
My 2 cents: probably this has been discussed before, but using |
Thanks for the contribution! This certainly looks good; it looks like the review missed that it wasn't using an actual queue when making it an instance variable rather than a one-off. However, we should get a test in place for this in the PR to ensure that it doesn't regress again. There aren't currently native unit tests in place for it, but based on the discussion in the issue it seems like an integration tests that does two sets in row than waits for both to succeed should be able to catch this. If you can add it that works be great, otherwise I can take a look tomorrow. This will also need a version and CHANGELOG update. |
It's definitely not unlikely; it's used 100% of the time (to send back in the response).
There is no mechanism on iOS for NSUserDefaults to fail and that to be communicated to the caller, so on iOS one has to trust that it always succeeds. That's not the case on Android. The existence of one behavior on one platform doesn't mean that we should treat a different API on a different platform as if it had that behavior. |
Test added; I verified that it triggered the bug for me locally without the fix, so it would catch the issue at least sometimes; I don't see a way to test it deterministically unfortunately. |
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!
@stuartmorgan I guess that if you set a value 20 times in a loop without Besides, I know that you return the appropriate value on Android, I just doubt that many developers check the return code from |
There is a fundamental difference between an individual developer choosing not to check the return code, and the plugin making it impossible for any developer to check the return code. |
@stuartmorgan As a former Android java dev (where |
Please provide sources for that, because it's not what I'm seeing: https://developer.android.com/reference/android/content/SharedPreferences.Editor#commit() :
https://developer.android.com/reference/android/content/SharedPreferences.Editor#apply() :
|
…d preferences on Android (flutter/plugins#3684)
I have nothing to add to your excerpts about Android. I guess that the notion of synchronous calls on the main thread on Android (probably one of the first things you learn to avoid on Android java) (and where it's suggested to consider using You consider that the developer should be given the possibility to check synchronously the return code, it's safer, fair enough. I have absolutely no idea about how I could gracefully add the return code checks to all my That's all I have to say about that. |
* master: (49 commits) Prep for alignment with Flutter analysis options (flutter#3703) [google_maps_flutter_platform_interface] Mark constructors as const for ids (flutter#3718) [image_picker] Endorse image_picker_for_web (flutter#3717) Add missing licenses, and add a check (flutter#3720) [ci] Add libgcrypt to Docker image. (flutter#3711) Reorder the checkboxes in the PR template (flutter#3666) Re-endorse connectivity_for_web (flutter#3708) Fix missing declaration of windows' default_package (flutter#3705) Typos in comments (flutter#2846) Skip flutter upgrade for pod linting Cirrus task (flutter#3700) [cross_file] Delete. (flutter#3698) [tool] Improve check version ci so that it enforces the version in CHANGELOG and pubspec matches. (flutter#3678) Streamline CI setup, and reenable macOS credits (flutter#3697) [video_player] fixed misleading size and aspect ratio documentation (flutter#3668) [image_picker] Implemented 2860 and added Unit Test to test functionality (flutter#3685) [shared_preferences] Fix concurrent modification of the shared preferences on Android (flutter#3684) [extension_google_sign_in_as_googleapis_auth] Deleted. (flutter#3694) Skip pod lint tests (flutter#3692) [Video_Player] Remove the deprecated API reference. (flutter#3669) [google_sign_in] fix test(flutter#3690) ...
When value is set before the last value has been committed to the shared preferences, the commit of the last value is rejected with the following error:
java.util.concurrent.RejectedExecutionException: Task io.flutter.plugins.sharedpreferences.MethodCallHandlerImpl rejected from java.util.concurrent.ThreadPoolExecutor
.This happens because a
SynchronousQueue
is being used, which can handle only one request at a time and isn't really queue unless a request is removed or done.By replacing it with a
LinkedBlockingQueue
the commits are queue to execute one after another. This preserves the async nature of the library, prevents data loss and fixes theRejectedExecutionException
.This fixes this issue: [shared_preferences] 2.0.3 throws a lot of Java Tracebacks on Android
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
Pre-launch Checklist
[shared_preferences]
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.