Skip to content

Crash on Android due to faulty onDestroy() when js->go calls are in flight during destroy #5859

Description

@bafto

Wails version family

v3

Operating System

Android (experimental)

Description

I encountered a bug where I would get a crash when minimizing the my App on Android:

07-31 16:24:43.096 10758 10758 W cr_AwContents: WebView.destroy() called while WebView is still attached to window.
07-31 16:24:43.100 10758 10758 W WindowOnBackDispatcher: sendCancelIfRunning: isInProgress=false callback=android.view.ViewRootImpl$$ExternalSyntheticLambda14@d9795ca
07-31 16:24:43.105 10758 10758 D ViewRootImpl: Skipping stats log for color mode
07-31 16:24:43.157 10758 10758 W cr_AwContents: Application attempted to call on a destroyed WebView
07-31 16:24:43.157 10758 10758 W cr_AwContents: java.lang.Throwable
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at org.chromium.android_webview.AwContents.p(chromium-SystemWebViewGoogle6432.aab-stable-787112403:10)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at com.android.webview.chromium.WebViewChromium.evaluateJavaScript(chromium-SystemWebViewGoogle6432.aab-stable-787112403:47)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.webkit.WebView.evaluateJavascript(WebView.java:895)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at com.wails.app.WailsJSBridge.lambda$sendCallback$1$com-wails-app-WailsJSBridge(WailsJSBridge.java:137)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at com.wails.app.WailsJSBridge$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.os.Handler.handleCallback(Handler.java:1037)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.os.Handler.dispatchMessage(Handler.java:108)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.os.Looper.loopOnce(Looper.java:304)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.os.Looper.loop(Looper.java:430)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at android.app.ActivityThread.main(ActivityThread.java:9345)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at java.lang.reflect.Method.invoke(Native Method)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
07-31 16:24:43.157 10758 10758 W cr_AwContents: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:953)

To Reproduce

In the app I am regularly polling updates from the go backend and I think the bug occured when such a request was in-flight while the View was being destroyed.

Expected behaviour

It should not crash

Screenshots

No response

Attempted Fixes

I am not an expereinced Android native programmer, so I just asked Claude for a quick-fix and that worked for me:

In WailsJSBridge.java:

+    /**
+     * Marks this bridge's WebView as gone. Call before tearing down the
+     * WebView so callbacks from calls already running on {@link #executor}
+     * (e.g. a poll in flight when the Activity is destroyed) no-op instead of
+     * touching a destroyed WebView.
+     */
+    public void markDestroyed() {
+        destroyed = true;
+    }
+
     /**
      * Send a message to Go and return the response synchronously.
      * Called from JavaScript: wails.invoke(message)
@@ -134,7 +148,13 @@ public class WailsJSBridge {
             );
         }
 
-        webView.post(() -> webView.evaluateJavascript(js, null));
+        webView.post(() -> {
+            // Re-checked here, not just by callers before posting: destroy()
+            // can happen in the window between post() and this runnable
+            // actually executing on the UI thread.
+            if (destroyed) return;
+            webView.evaluateJavascript(js, null);
+        });
     }

In MainActivity.java:

@@ -57,6 +58,7 @@ public class MainActivity extends AppCompatActivity {
 
     private WebView webView;
     private WailsBridge bridge;
+    private WailsJSBridge jsBridge;
     // Battery: system-event receivers are registered only while the activity is
     // in the foreground (onStart) and torn down in onStop, so background battery/
     // network/screen broadcasts don't wake the app.
@@ -196,7 +198,8 @@ public class MainActivity extends AppCompatActivity {
         });
 
         // Add JavaScript interface for Go communication
-        webView.addJavascriptInterface(new WailsJSBridge(bridge, webView), "wails");
+        jsBridge = new WailsJSBridge(bridge, webView);
+        webView.addJavascriptInterface(jsBridge, "wails");
     }
 
     private void loadApplication() {
@@ -802,11 +805,26 @@ public class MainActivity extends AppCompatActivity {
     protected void onDestroy() {
         super.onDestroy();
         unregisterSystemEventReceivers();
+        // Mark the JS bridge destroyed before anything else below, so any
+        // invokeAsync call already running on its background executor - e.g.
+        // an in-flight AudioService.Progress() poll - finds the flag set and
+        // skips its evaluateJavascript callback instead of racing destroy().
+        if (jsBridge != null) {
+            jsBridge.markDestroyed();
+        }
         if (bridge != null) {
             bridge.shutdown();
         }
         if (webView != null) {
+            // WebView.destroy() while still attached to the view hierarchy
+            // logs "WebView.destroy() called while WebView is still attached
+            // to window" - detach it first.
+            ViewGroup parent = (ViewGroup) webView.getParent();
+            if (parent != null) {
+                parent.removeView(webView);
+            }
             webView.destroy();
+            webView = null;
         }
     }

But like I said, this is just a quick-and-dirty AI fix that worked for my specific issue, maybe you should look into it in more detail.

System Details

ails v3.0.0-alpha2.117 › Wails Doctor
                                                                                                                                                                                                                                                                                 
# System
        
┌───────────────────────────────────────────────────────────────────────────────┐
| Name                | Linux Mint                                              |
| Version             | 22.1                                                    |
| ID                  | linuxmint                                               |
| Branding            | 22.1 (Xia)                                              |
| Platform            | linux                                                   |
| Architecture        | amd64                                                   |
| Desktop Environment | i3                                                      |
| NVIDIA Driver       | N/A                                                     |
| XDG_SESSION_TYPE    | x11                                                     |
| CPU                 | 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz          |
| GPU                 | TigerLake-LP GT2 [Iris Xe Graphics] (Intel Corporation) |
| Memory              | 15GB                                                    |
└───────────────────────────────────────────────────────────────────────────────┘
                   
# Build Environment
                   
┌──────────────────────────────────────────────────────────────────────┐
| Wails CLI      | v3.0.0-alpha2.117                                   |
| Go Version     | go1.26.5                                            |
| -buildmode     | exe                                                 |
| -compiler      | gc                                                  |
| CGO_CFLAGS     |                                                     |
| CGO_CPPFLAGS   |                                                     |
| CGO_CXXFLAGS   |                                                     |
| CGO_ENABLED    | 1                                                   |
| CGO_LDFLAGS    |                                                     |
| DefaultGODEBUG | cryptocustomrand=1,tlssecpmlkem=0,urlstrictcolons=0 |
| GOAMD64        | v1                                                  |
| GOARCH         | amd64                                               |
| GOOS           | linux                                               |
└──────────────────────────────────────────────────────────────────────┘
              
# Dependencies
              
┌──────────────────────────────────────────────────────────────────────────────────────┐
| *Android NDK            | /home/bafto/Android/Sdk/ndk/29.0.13113456                  |
| *Android SDK            | /home/bafto/Android/Sdk                                    |
| *Android platform-tools | Installed                                                  |
| *Java (Android)         | openjdk version "21.0.11" 2026-04-21                       |
| gcc                     | 12.10ubuntu1                                               |
| gtk3 (legacy)           | 3.24.41-4ubuntu1.3                                         |
| gtk4                    | 4.14.5+ds-0ubuntu0.10                                      |
| npm                     | 11.5.1                                                     |
| pkg-config              | 1.8.1-2build1                                              |
| webkit2gtk (legacy)     | 2.52.3-0ubuntu0.24.04.1                                    |
| webkitgtk-6.0           | 2.52.3-0ubuntu0.24.04.1                                    |
| docker                  | *Docker version 29.7.0, build c1eba93 (daemon not running) |
|                                                                                      |
└────────────────────────────── * - Optional Dependency ───────────────────────────────┘
         
# Signing
         
┌─────────────────────────────────────────────┐
| macOS Signing   | Not configured            |
| Windows Signing | Not configured            |
| Linux Signing   | Not configured            |
└─────────────────────────────────────────────┘
                     
# Checking for issues
                     
 SUCCESS  No issues found
           
# Diagnosis
           
 SUCCESS  Your system is ready for Wails development!

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    No type

    Projects

    Status
    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions