I’m using Sentry-Android 2.3.0 SDK to collect android crashes and ANR, for the past few months, there were a couple of weird ANRs showing up. All of them happened when the user turned on the device after some time, all of them happened in the MessageQueue.next
method. After digging in the Sentry SDK source code a bit, I found the core logic for dealing with ANR in Android lies in class ANRWatchDog.java, which IMHO can be simplified as follows:
public class Test { BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(); class MainThread extends Thread { public void run() { while (!isInterrupted()) { Runnable r; try { r = queue.take(); } catch (InterruptedException e) { return; } r.run(); } } } class WorkerThread extends Thread { private AtomicLong tick = new AtomicLong(0); private AtomicBoolean reported = new AtomicBoolean(false); private final Runnable ticker = new Runnable() { public void run() { tick = new AtomicLong(0); reported.set(false); } }; public void run() { while (!isInterrupted()) { boolean needPost = tick.get() == 0; tick.addAndGet(100L); if (needPost) { queue.add(ticker); } try { Thread.sleep(100L); } catch (InterruptedException e) { return; } if (tick.get() != 0 && !reported.get()) { // TODO: if ActivityManager available, further check reported.set(true); throw new RuntimeException("Bang!"); } } } } }
My question is, shouldn’t the tick variable be volatile
? Can this code cause visibility issues? If so, will this code result in false alarm in production code?
Advertisement
Answer
afaik AtomicLong
getter and setter read/write from volatile fields so not necessary, we’ve made improvements to this algo to avoid false/positives, please upgrade the SDK to the latest version.
One of the main changes is: https://github.com/getsentry/sentry-java/blob/main/sentry-android-core/src/main/java/io/sentry/android/core/ANRWatchDog.java#L95-L117