Skip to content
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

@capacitor/geolocation : RuntimeException - java.util.ConcurrentModificationException #1957

Open
neogenz opened this issue Dec 8, 2023 · 6 comments
Labels

Comments

@neogenz
Copy link

neogenz commented Dec 8, 2023

Bug Report

Plugin(s)

  • Capacitor Geolocation Plugin 5.0.6

Capacitor Version

npx cap doctor
💊   Capacitor Doctor  💊

Latest Dependencies:

  @capacitor/cli: 5.5.1
  @capacitor/core: 5.5.1
  @capacitor/android: 5.5.1
  @capacitor/ios: 5.5.1

Installed Dependencies:

  @capacitor/ios: not installed
  @capacitor/cli: 5.5.1
  @capacitor/core: 5.5.1
  @capacitor/android: 5.5.1

[success] Android looking great! 👌

Platform(s)

  • Android (v8 to 14)

Current Behavior

When the application, which uses the Capacitor Geolocation plugin, is put into the background for a few minutes and then brought back to the foreground, the app crashes with a java.util.ConcurrentModificationException. This exception occurs in the GeolocationPlugin.handleOnResume method, as detailed in the stack trace provided.

java.util.ConcurrentModificationException: null
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1441)
    at java.util.HashMap$ValueIterator.next(HashMap.java:1470)
    at com.capacitorjs.plugins.geolocation.GeolocationPlugin.handleOnResume(GeolocationPlugin.java:49)
    at com.getcapacitor.Bridge.onResume(Bridge.java:1254)
    at com.getcapacitor.BridgeActivity.onResume(BridgeActivity.java:86)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1364)
    at android.app.Activity.performResume(Activity.java:7490)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4256)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4328)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
    at android.os.Handler.dispatchMessage(Handler.java:108)
    at android.os.Looper.loop(Looper.java:166)
    at android.app.ActivityThread.main(ActivityThread.java:7529)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
java.lang.RuntimeException: Unable to resume activity {ch.tpg.boldor/ch.tpg.boldor.MainActivity}: java.util.ConcurrentModificationException
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4288)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4328)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
    at android.os.Handler.dispatchMessage(Handler.java:108)
    at android.os.Looper.loop(Looper.java:166)
    at android.app.ActivityThread.main(ActivityThread.java:7529)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

Exemple of scenario, it is always more or less same
image

We have lot of crash due to this error in production on our app.

Expected Behavior

The expected behavior is that the app should resume normally from the background without any crash or exception related to the Geolocation plugin.

Additional Context

This issue seems to occur due to modifications in the HashMap within the GeolocationPlugin while iterating over it. This problem surfaces specifically when handling the onResume lifecycle event in Android.

To reproduce

https://github.com/neogenz/capacitor-geolocation-sample

The scenario is simple : on Android app, pass app in background, wait (only some ms is enough) then put it back in foreground -> crash

The issue is really complicated to reproduce. To "force" it, modify java/com/capacitorjs/plugins/geolocation/GeolocationPlugin.java and update this code :

@Override
    protected void handleOnResume() {
      super.handleOnResume();

      // This loop is to force crash when switch background/foreground more times
      for (int i = 0; i < 5; i++) {
        new Thread(() -> {
          try {
            Thread.sleep(10); // Réduire le délai
            if (!watchingCalls.isEmpty()) {
              watchingCalls.remove(watchingCalls.keySet().iterator().next());
            }
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }).start();
      }

      for (PluginCall call : watchingCalls.values()) {
          startWatch(call);
      }
    }

And I reproduce it more easily on physical device (on virtual too, but it is less frequent)

We have tried a fix with our team but we don't know if it is correct without knowing all context of Geolocation / Capacitor code :

@Override
    protected void handleOnResume() {
        super.handleOnResume();
        List<PluginCall> watchingCallsValues = new ArrayList<PluginCall>(watchingCalls.values());
        for (PluginCall call : watchingCallsValues) {
            startWatch(call);
        }
    }
@ionitron-bot ionitron-bot bot added the triage label Dec 8, 2023
@neogenz
Copy link
Author

neogenz commented Jan 31, 2024

Any news ?

1 similar comment
@neogenz
Copy link
Author

neogenz commented Feb 29, 2024

Any news ?

@neogenz
Copy link
Author

neogenz commented Jun 20, 2024

any news ?

@neogenz
Copy link
Author

neogenz commented Aug 2, 2024

We are experiencing errors on iOS in production for many clients. I don't know if it is due to the plugin itself or something related to our usage of it.
image

@elazarza
Copy link

elazarza commented Nov 19, 2024

having the same issue, app crashes in the same place as OP is describing.
hard to reproduce, but has something to do with multiple thread modifying HashMap on resume.

Dump from logcat on crash:

FATAL EXCEPTION: main Process: com.myappname, PID: 2298 java.lang.RuntimeException: Unable to resume activity {com.myappname/commyappname.MainActivity}: java.util.ConcurrentModificationException at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4014) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4046) at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1948) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7050) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965) Caused by: java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(HashMap.java:1441) at java.util.HashMap$ValueIterator.next(HashMap.java:1470) at com.capacitorjs.plugins.geolocation.GeolocationPlugin.handleOnResume(GeolocationPlugin.java:49) at com.getcapacitor.Bridge.onResume(Bridge.java:1267) at com.getcapacitor.BridgeActivity.onResume(BridgeActivity.java:85) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1412) at android.app.Activity.performResume(Activity.java:7572) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4006) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4046)  at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:51)  at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:145)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1948)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:214)  at android.app.ActivityThread.main(ActivityThread.java:7050)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)  2024-11-19 16:41:22.602 2298-2298 Process com.myappname I Sending signal. PID: 2298 SIG: 9

` Capacitor Doctor

Latest Dependencies:

@capacitor/cli: 6.1.2
@capacitor/core: 6.1.2
@capacitor/android: 6.1.2
@capacitor/ios: 6.1.2

Installed Dependencies:

@capacitor/cli: 5.5.1
@capacitor/android: 5.5.1
@capacitor/core: 5.5.1
@capacitor/ios: 5.5.1`

@neogenz
Copy link
Author

neogenz commented Nov 19, 2024

having the same issue, app crashes in the same place as OP is describing. hard to reproduce, but has something to do with multiple thread modifying HashMap on resume.

It's still a major production issue in our app... 😮‍💨

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

No branches or pull requests

2 participants