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

Deadlock on main thread creating ANR in the app in MonitoringStatus.regions() #1108

Open
kevingilles opened this issue Oct 25, 2022 · 4 comments

Comments

@kevingilles
Copy link

Expected behavior

altbeacon would not block the main thread

Actual behavior

I can find a deadlock on the mainThread that creates ANR. You can find the lock in the screenshot below.

Steps to reproduce this behavior

I'm not sure, it's sporadic and I haven't reproduced it myself. II can see it in Firebase though.

Mobile device model and OS version

Android 12 - Galaxy A32

Android Beacon Library version

2.19.4

Deadlock on my app

@davidgyoung
Copy link
Member

Thanks for this report.

I have been starting at the code for 30 minutes, but I can't see how a deadlock happened here. AFAICT, here is what is happening when this happens:

The main thread received a new scan via intent, and tried to restore scan state to schedule a new scan job with this line ScanState scanState = ScanState.restore(context);, this caused it to get exclusive access to the ScanState object in this line: synchronized (ScanState.class). It continues and inside that block, it ultimately wants to call this method scanState.getMonitoringStatus().regions() but gets blocked as it is synchronizedMonitoringStatus class which is synchronized here: public synchronized Set<Region> regions() { return getRegionsStateMap().keySet(); }

Meanwhile, another thread was trying to start beacon ranging, which also caused that thread to try to restore scan state with the same call to ScanState scanState = ScanState.restore(context);, it gets blocked on the synchronized (ScanState.class)

So in summary:

  • The main thread is inside a synchronized block on ScanState.class and is blocked waiting to call a synchronized method on MonitoringStatus.
  • A background thread is waiting to get synchronized access to the ScanState.class.

Why is this a deadlock? I see no reason why the main thread cannot call the method on MonitoringStatus. The second thread is not accessing it.

Unless there is another thread in the mix not shown in the screenshot?

@kevingilles
Copy link
Author

It is indeed eluding me too, thank you for your time. I managed to get my hands on 2 more exemples that I might help with context.
I hope this information is useful, I remain available to test anything on my end you would find relevant.

Here is the first one:

Capture d’écran 2022-10-28 à 15 03 32

And here is the second one (2 different Screenshots)

Capture d’écran 2022-10-28 à 15 04 19

Capture d’écran 2022-10-28 à 15 04 32

Finally, the 3rd one

Capture d’écran 2022-10-28 à 15 11 51

Capture d’écran 2022-10-28 à 15 12 02

@kevingilles
Copy link
Author

kevingilles commented Nov 9, 2022

Could this happen if I try to scan using altbeacon while one of my imported lib did the same?

@davidgyoung
Copy link
Member

While it is possible that contributes to the cause, but I don't think that would fundamentally change anything. Because the BeaconManger is a singleton it is shared by both your app and all libraries your app uses, so any problem like this might happen regardless of whether all calls are from your app or calls are also made from a dependent library.

From the stack traces I have seen so far, I don't understand why the threads are blocked. There must be something wrong with my understanding about how synchronized is working in this case.

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

No branches or pull requests

2 participants