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

Real ANR timeout #40

Open
tprochazka opened this issue Jun 11, 2019 · 2 comments
Open

Real ANR timeout #40

tprochazka opened this issue Jun 11, 2019 · 2 comments

Comments

@tprochazka
Copy link

I tested your library and I found that reaction on ANR is much bigger than the value set in constructor by new ANRWatchDog(10000 /*timeout*/).start();

I found that it is caused by this code

        try {
            Thread.sleep(interval);
        } catch (InterruptedException e) {
            _interruptionListener.onInterrupted(e);
            return ;
        }

If there is no ANR, your thread basically sleeps for 10000 ms in this case.
During this 10s can happen that thread is blocked, for example in the middle.
So it is already 5s blocked at the end, but tick has arrived before it happens.
So it will sleep again 10s, and then it detects ANR after 15s.
So theoretically it can be almost double of configured time.

The only workaround is to use low timeout interval, for example, 500ms
And then use ANRInterceptor and detect real 10s here.

But this behavior is not clear from the documentation.

@tprochazka
Copy link
Author

tprochazka commented Jun 11, 2019

Another weird thing is that timeout in the constructor is int, but time in ANRInterceptor is Long.

@Vandalko
Copy link

Vandalko commented Jul 13, 2020

Oh, it helped me figure out why obvious Thread.sleep(7000) is not caught sometimes...
Ended up with:

        new ANRWatchDog(500)
                .setANRInterceptor(new ANRWatchDog.ANRInterceptor() {

                    private long lastReportTs = 0L;

                    @Override
                    public long intercept(long duration) {
                        if (duration >= 2500L && System.currentTimeMillis() - lastReportTs > duration) {
                            final IllegalStateException exception = new IllegalStateException("ANR");
                            final Thread mainThread = Looper.getMainLooper().getThread();
                            exception.setStackTrace(mainThread.getStackTrace());
                            Log.e("ANRWatchDog",
                                    "ANR is detected",
                                    exception
                            );

                            lastReportTs = System.currentTimeMillis();
                        }

                        return Math.min(5000L - duration, 500L);
                    }
                })
                .setANRListener(error -> {
                    Log.e("ANRWatchDog",
                            "ANR is detected",
                            error
                    );
                })
                .start();

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