Repository: godot
Issue: Android - app crash on exit
Labels: bug,platform:android,needs testing,topic:dotnet,crash

### Godot version

3.6.beta3, 3.5.stable

### System information

Android 13 - OnePlus 9 - OxygenOS 13.1 (but seems to affect all Androids)

### Issue description

I detected a bunch of ANRs/crashes happening in the wild on my released Android game (stacktrace below). The crashes happen on app exit. Apparently Godot does some cleanup but does so in a way that causes a SIGTRAP.

I was able to trace it back and create a sample project where it's 100% reproducible on my Android phone, see below. It's definitely related to connecting to a signal in the root of the scene tree, and is also possibly related to Autoloading (not sure on that though). C#/Mono also seem to play a role, so I uploaded a C#/Mono reproduction project.

The weirdest thing I came across by accident while trying out stuff: if I throw an exception in the _ExitTree() method, the app exits without a big crash. The exception gets logged, but otherwise the app seems to close without ANR. This is obviously not a proper fix, but I'm considering putting this exception throw in to prevent the ANRs as a temporary fix.

You might say that ANRs on app exit are not a big deal because the app would close anyway, but AFAIK Google does not like it if apps crash too often and might actively downrank (or even de-list?) it in the Play Store. And if all Godot driven games are affected, this might be important. At the very least, it causes a lot of unneccessary ANRs in the Play Console that cause devs like me to go "huh..." ;)

The info in the Google Play console looked like this (looks like that particular user was turning their screen off, causing the app exit):
```
Native method - org.godotengine.godot.GodotLib.ondestroy
Broadcast of Intent { act=android.intent.action.SCREEN_OFF }
```
Stacktrace looks like this, probably not too helpful on its own:
```
  #00  pc 0x00000000000acdb8  /apex/com.android.runtime/lib64/bionic/libc.so (nanosleep+8)
  #01  pc 0x0000000000befcfc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #02  pc 0x0000000001862624  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #03  pc 0x00000000010fcc20  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #04  pc 0x00000000010fd01c  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #05  pc 0x0000000000df8b1c  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #06  pc 0x0000000001942c2c  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #07  pc 0x0000000000d5b108  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #08  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #09  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #10  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #11  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #12  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #13  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #14  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #15  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #16  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #17  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #18  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #19  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #20  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #21  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #22  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #23  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #24  pc 0x0000000000d5afcc  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #25  pc 0x0000000000d5eee8  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #26  pc 0x0000000000d80198  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #27  pc 0x000000000063f584  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/split_config.arm64_v8a.apk
  #28  pc 0x0000000000461754  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148)
  #29  pc 0x0000000000209398  /apex/com.android.art/lib64/libart.so (nterp_helper+152)
  #30  pc 0x00000000004f245e  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (org.godotengine.godot.Godot.onDestroy+82)
  #31  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #32  pc 0x00000000001d362a  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.Fragment.performDestroy+38)
  #33  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #34  pc 0x00000000001cc0de  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentStateManager.destroy+254)
  #35  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #36  pc 0x00000000001cc6d4  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentStateManager.moveToExpectedState+536)
  #37  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #38  pc 0x00000000001d507e  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete+10)
  #39  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #40  pc 0x00000000001d5748  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.SpecialEffectsController$Operation.cancel+36)
  #41  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #42  pc 0x00000000001d611e  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.SpecialEffectsController.forceCompleteAllOperations+430)
  #43  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #44  pc 0x00000000001c8c08  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentManager.dispatchStateChange+72)
  #45  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #46  pc 0x00000000001c88f4  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentManager.dispatchDestroy+20)
  #47  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #48  pc 0x00000000001c40b0  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentController.dispatchDestroy+8)
  #49  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  #50  pc 0x00000000001c2d92  /data/app/~~4PiEUVYa-E0tGhatBEWVeg==/org.maxbytes.lfs--C-ADiKbGjrQto4_DmmTkw==/oat/arm64/base.vdex (androidx.fragment.app.FragmentActivity.onDestroy+10)
  #51  pc 0x000000000020a254  /apex/com.android.art/lib64/libart.so (nterp_helper+3924)
  at org.godotengine.godot.GodotLib.ondestroy (Native method)
  at org.godotengine.godot.Godot.onDestroy (Godot.java:861)
  at androidx.fragment.app.Fragment.performDestroy (Fragment.java:3219)
  at androidx.fragment.app.FragmentStateManager.destroy (FragmentStateManager.java:774)
  at androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:350)
  at androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete (SpecialEffectsController.java:745)
  at androidx.fragment.app.SpecialEffectsController$Operation.cancel (SpecialEffectsController.java:597)
  at androidx.fragment.app.SpecialEffectsController.forceCompleteAllOperations (SpecialEffectsController.java:332)
  at androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:3132)
  at androidx.fragment.app.FragmentManager.dispatchDestroy (FragmentManager.java:3107)
  at androidx.fragment.app.FragmentController.dispatchDestroy (FragmentController.java:334)
  at androidx.fragment.app.FragmentActivity.onDestroy (FragmentActivity.java:330)
  at org.godotengine.godot.FullScreenGodotApp.onDestroy (FullScreenGodotApp.java:81)
  at android.app.Activity.performDestroy (Activity.java:8599)
  at android.app.Instrumentation.callActivityOnDestroy (Instrumentation.java:1452)
  at android.app.ActivityThread.performDestroyActivity (ActivityThread.java:5411)
  at android.app.ActivityThread.handleDestroyActivity (ActivityThread.java:5457)
  at android.app.servertransaction.DestroyActivityItem.execute (DestroyActivityItem.java:47)
  at android.app.servertransaction.ActivityTransactionItem.execute (ActivityTransactionItem.java:45)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:179)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2306)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:7918)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
```


### Steps to reproduce

In an otherwise empty/new project, adding this code and enabling it as an Autoload crashes the Android app on exit:
```
using Godot;
using System.Diagnostics;

public class new_script : Node
{
    public override void _Ready()
    {
        Debug.WriteLine("_Ready running");
        GetTree().Connect("node_added", this, nameof(OnNodeAdded));
        Debug.WriteLine("node_added signal connected");
    }

    public override void _ExitTree()
    {
        Debug.WriteLine("_ExitTree running");
        //throw new global::System.Exception(); // uncommenting this makes the app NOT(!) crash on exit
    }

    protected void OnNodeAdded(Node n)
    {
        // NO-OP
    }
}
```

Tip for reproduction: some (most?) Android phones have a setting in the developer tools that toggles whether apps should be immediately closed when hidden. After enabling this, you can force an app exit by simply tabbing out/going to the main screen/locking the screen. See [https://github.com/godotengine/godot/issues/51021#issuecomment-895438447](https://github.com/godotengine/godot/issues/51021#issuecomment-895438447) for a better explanation.

### Minimal reproduction project

[android_crash_on_exit_repro.zip](https://github.com/godotengine/godot/files/12507287/android_crash_on_exit_repro.zip)