ANR in com.unity3d.player.UnityPlayer.updateDisplayInternal

Hi I get a lot of ANR related to com.unity3d.player.UnityPlayer.updateDisplayInternal.
Unity 2019.4.25f1

The common flow is :
…App Stoped/App Paused

→ com.unity3d.player.UnityPlayer$21.surfaceDestroyed

→ com.unity3d.player.UnityPlayer.updateDisplayInternal
→ java.util.concurrent.Semaphore.tryAcquire

Here is more detailed log(I use ANR watchdog to get it):

sun.misc.Unsafe.park (Unsafe.java)
java.util.concurrent.locks.LockSupport.parkNanos (LockSupport.java:230)
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos (AbstractQueuedSynchronizer.java:1063)
java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos (AbstractQueuedSynchronizer.java:1358)
java.util.concurrent.Semaphore.tryAcquire (Semaphore.java:415)
com.unity3d.player.UnityPlayer.updateDisplayInternal (Unknown Source:54)
com.unity3d.player.UnityPlayer.updateGLDisplay (Unknown Source:5)
com.unity3d.player.UnityPlayer.access$1100
com.unity3d.player.UnityPlayer$21.surfaceDestroyed (Unknown Source:4)
android.view.SurfaceView.updateSurface (SurfaceView.java:879)
android.view.SurfaceView.windowStopped (SurfaceView.java:315)
android.view.ViewRootImpl.setWindowStopped (ViewRootImpl.java:1977)
android.view.WindowManagerGlobal.setStoppedState (WindowManagerGlobal.java:709)
android.app.Activity.performStop (Activity.java:8181)
android.app.ActivityThread.callActivityOnStop (ActivityThread.java:4987)
android.app.ActivityThread.handleSleeping (ActivityThread.java:5124)
android.app.ActivityThread.access$2500 (ActivityThread.java:270)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2149)
android.os.Handler.dispatchMessage (Handler.java:107)
android.os.Looper.loop (Looper.java:237)
android.app.ActivityThread.main (ActivityThread.java:7948)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1075)

And here is function UnityPlayer.updateDisplayInternal

private boolean updateDisplayInternal(final int var1, final Surface var2) {
        if (n.c() && this.mState.e()) {
            final Semaphore var3 = new Semaphore(0);
            Runnable var4 = new Runnable() {
                public final void run() {
                    UnityPlayer.this.nativeRecreateGfxState(var1, var2);
                    var3.release();
                }
            };
            if (var1 == 0) {
                if (var2 == null) {
                    this.m_MainThread.b(var4);
                } else {
                    this.m_MainThread.c(var4);
                }
            } else {
                var4.run();
            }

            if (var2 == null && var1 == 0) {
                try {
                    if (!var3.tryAcquire(4L, TimeUnit.SECONDS)) {
                        g.Log(5, "Timeout while trying detaching primary window.");
                    }
                } catch (InterruptedException var5) {
                    g.Log(5, "UI thread got interrupted while trying to detach the primary window from the Unity Engine.");
                }
            }

            return true;
        } else {
            return false;
        }
    }

Do anyone have similar problem or any idea to overcome it?
Thank you.

3 Likes

I think someone reported it in the past, but since there’s no exact steps on how to repro it, it wasn’t fixed. One of the potential fixes for this is to set https://docs.unity3d.com/ScriptReference/Screen-sleepTimeout.html to SleepTimeout.NeverSleep.

Thank you Tomas!! I’ll try it.

I can’t reproduce on my end too. It’s happened on wide range of devices, android versions.
The only notable info is 76% of this ANR is when app in background.

Out of curiosity, how do you know that app is in background? Because of the stacktrace?

Hi Tomas, Crashlytic has that info.

2 Likes
    public  void pause() {
        Log.i(TAG, "pause: start--"+isShow);
        if(true){
            super.pause();
            for (int i = 0; i < getChildCount(); i++) {
                final View child =getChildAt(i);
                if(null!=child){
                    Log.i(TAG,"pause---"+child.toString());
                    post(new Runnable() {
                        @Override
                        public void run() {
                            child.setVisibility(View.GONE);
                        }
                    });

                }

            }
            windowFocusChanged(false);
            isShow=false;
        }
        Log.i(TAG, "pause: end");
    }

Is there a solution to this problem?I modified the pasue () of unityplay and called pause (), which caused the same problem.

Unfortunately, I didn’t find any. Tried to remove all code in OnDisable, OnDestroy, OnApplicationPause, OnApplicationQuit. But the ANR still high.

same issue

Hi , any update on this ?

@Tomas1856 The majority of our ANR start with com.unity3d.player.UnityPlayer.surfaceDestroyed too. My guess is UnityPlayer blocks ‘main’ thread waiting on some semaphore for something queued on to ‘UnityMain’ or other thread. I have no access to sources to check this hypothesis and I have no clues how to resolve that ANR.
Can you help with investigation, please?

up

Up top, i have same issue

up

main (timed waiting): tid=1 systid=16340
       at sun.misc.Unsafe.park(Native method)
       at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedNanos(AbstractQueuedSynchronizer.java:1063)
       at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1358)
       at java.util.concurrent.Semaphore.tryAcquire(Semaphore.java:415)
       at com.unity3d.player.UnityPlayer.updateDisplayInternal(unavailable)
       at com.unity3d.player.UnityPlayer.updateGLDisplay(unavailable)
       at com.unity3d.player.UnityPlayer.access$1100(unavailable)
       at com.unity3d.player.UnityPlayer$19.surfaceDestroyed(unavailable)
       at android.view.SurfaceView.notifySurfaceDestroyed(SurfaceView.java:1943)
       at android.view.SurfaceView.updateSurface(SurfaceView.java:1239)
       at android.view.SurfaceView.setWindowStopped(SurfaceView.java:291)
       at android.view.SurfaceView.surfaceDestroyed(SurfaceView.java:1767)
       at android.view.ViewRootImpl.notifySurfaceDestroyed(ViewRootImpl.java:1891)
       at android.view.ViewRootImpl.setWindowStopped(ViewRootImpl.java:1826)
       at android.view.WindowManagerGlobal.setStoppedState(WindowManagerGlobal.java:700)
       at android.app.Activity.performStop(Activity.java:8398)
       at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4981)
       at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:4960)
       at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5034)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:233)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2135)
       at android.os.Handler.dispatchMessage(Handler.java:106)
       at android.os.Looper.loop(Looper.java:236)
       at android.app.ActivityThread.main(ActivityThread.java:8059)
       at java.lang.reflect.Method.invoke(Native method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)

Is it reproducible for you locally, also which device is this? Cheers

I can’t reproduce it locally, this is from Crashlytics.

This is on Xiaomi Redmi Note 10 Pro

7842021--994188--upload_2022-1-26_12-6-44.jpg

7842021--994191--upload_2022-1-26_12-7-21.png

According to stacktrace, it seems to be happening when the application goes to background.

So anyone experiencing this, can you try to do:

  • Start logcat and filter by your app Package Selection | Android Logcat | 1.2.3
  • Start your game
  • Hit Home Button, thus putting the app to background
  • And then resume the app (Using phone system button Overview, shaped is square or with several lines)
  • Repeat this multiple times

If all good, the app shouldn’t crash, and you should see in logcat onPause/onResume messages for your app.

1 Like

I made this batch file for Windows which puts app to background and resumes it multiple times.

  • Modify Android SDK path in the script

  • Ensure your phone can be unlocked without pin or similar

  • Launch the application

  • In Unity, via logcat package, start filtering messages for your application

  • Run the batch script

  • It will lock/unlock the phone multiple times

  • After unlocking the phone your app should be the one which is running, if not, something’s wrong

  • See if your app crashes.

echo off
SET ANDROID_SDK=G:\UnityInstalls\2022.1.0b1\Editor\Data\PlaybackEngines\AndroidPlayer\SDK

SET ADB="%ANDROID_SDK%builds\platform-tools\adb.exe"
SET TIME_BETWEEN_COMMANDS=1

for /l %%x in (1, 1, 100) do (
   echo Starting Iteration %%x
   timeout /T %TIME_BETWEEN_COMMANDS% /NOBREAK
   call %ADB% shell input keyevent 6
   timeout /T %TIME_BETWEEN_COMMANDS% /NOBREAK
   call %ADB% shell input keyevent 82
   timeout /T %TIME_BETWEEN_COMMANDS% /NOBREAK
   call %ADB% shell input swipe 100 100 100 200
)

echo Test Done
pause
2 Likes

Yes it crashes because Activity.onPause in main (as I can see from crash logs) is synchronized with UnityMain thread via a semaphore lock. Thus the main can be blocked by heavy operation in UnityMain thread. In our case it is a loading.

2020.3.0f1

Loading ? Why are you loading, while the app tries to pause itself?

  1. We do loading at Unity Main. Currently it is a heavy synchronous routine but it is a script running at Unity Main and technically it must not cause an ANR.

  2. Player minimizes his app and it goes to background. UnityPlayerActivity.onPause is triggered by Android on the main thread.

  3. Currently I believe that UnityPlayerActivity.onPause waits for UnityMain which is busy loading our files. main is blocked - ANR is fired. That’s it.