Skip to content

[Android] App is killed when the WebView renderer goes away while an InAppWebView is being disposed #2945

Open

Description

@BottlePumpkin

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

On Android, if the WebView renderer process goes away while an InAppWebView is being disposed, Android WebView terminates the whole app. This happens even when the app sets useOnRenderProcessGone: true and handles onRenderProcessGone for every WebView it still uses.

InAppWebView.dispose() does not destroy the WebView right away. It swaps in an anonymous WebViewClient, calls loadUrl("about:blank"), and calls destroy() only from that client's onPageFinished:

Until that onPageFinished runs, the WebView is still alive and attached to the renderer. If the renderer goes away in that window, Android WebView asks this WebView through WebViewClient.onRenderProcessGone. The anonymous client does not override it, so the default returns false. The API docs describe what happens then: "otherwise, application will crash if render process crashed, or be killed if render process was killed by the system."

The plugin's regular clients cannot help here either. dispose() sets channelDelegate to null first, and InAppWebViewClient(Compat).onRenderProcessGone then falls through to super (false) anyway (L793-L803).

A common way to hit this: the app recovers from a renderer crash by recreating the InAppWebView (new key), which disposes the old one. If the renderer dies again shortly afterwards, for example from another low-memory kill, the old WebView is still waiting for about:blank and takes the app down. Popping a route that contains an InAppWebView opens the same window. We first saw this in production.

How long the window lasts:

  • Kill: about:blank loads in a new renderer, and destroy() ran 13–149 ms after dispose() started.
  • Crash: the renderer stays frozen while its crash is being reported (~2.5 s here), so about:blank cannot finish. The window lasts until the crash is reported.

Expected Behavior

The app survives. It handles onRenderProcessGone for every WebView it still uses, and the WebView being disposed has nothing left to recover.

Proposed fix: handle onRenderProcessGone in the dispose client by destroying right away and reporting it as handled. I'll open a PR.

setWebViewClient(new WebViewClient() {
  public void onPageFinished(WebView view, String url) {
    destroy();
  }

  @RequiresApi(api = Build.VERSION_CODES.O)
  @Override
  public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
    destroy();
    return true;
  }
});

Steps with code example to reproduce

Minimal repro app: https://github.com/BottlePumpkin/flutter_inappwebview-render-gone-repro

It has one InAppWebView and no other WebViews. The renderer is terminated from inside the app with WebViewRenderProcess.terminate() (didCrash=false) or chrome://crash (didCrash=true). The README has the steps and every scenario.

  1. Show an InAppWebView with InAppWebViewSettings(useOnRenderProcessGone: true). In onRenderProcessGone, recreate it with a new Key.
  2. Terminate the renderer (WebViewCompat.getWebViewRenderProcess(webView).terminate()). The app handles it and the old WebView is disposed.
  3. Terminate the respawned renderer within ~50–150 ms, before the old WebView's about:blank has finished.
InAppWebView(
  key: ValueKey('home-$_gen'),
  initialData: InAppWebViewInitialData(data: '<h1>gen $_gen</h1>'),
  initialSettings: InAppWebViewSettings(useOnRenderProcessGone: true),
  onRenderProcessGone: (controller, detail) => setState(() => _gen++), // recreate -> old one is disposed
)

App killed out of 10 cold starts:

scenario before with the fix
kill → recreate → kill the respawned renderer 10/10 0/10
renderer terminated right after dispose() issues about:blank 10/10 0/10
pop a page with a WebView, kill right after 3/10 0/10
crash the renderer, pop a page with a WebView while the crash is being reported 9/10 0/10

Stacktrace/Logs

Logs

The only extra logging is in the dispose client (IAWV-dispose tag), and its return value is unchanged.

didCrash=false (terminate / low-memory kill):

E chromium: [ERROR:android_webview/browser/aw_browser_terminator.cc:176] Renderer process (31109) crash detected (code -1).
W IAWV-dispose: dispose client onRenderProcessGone id=259602995 url=about:blank didCrash=false returns=false
E chromium: [ERROR:android_webview/browser/aw_browser_terminator.cc:124] Render process (31109) kill (OOM or update) wasn't handed by all associated webviews, killing application.
I ActivityManager: Process dev.repro.repro_app (pid 31075) has died: fg  TOP

didCrash=true (renderer crash):

E chromium: [ERROR:android_webview/browser/aw_browser_terminator.cc:176] Renderer process (9113) crash detected (code 11).
W IAWV-dispose: dispose client onRenderProcessGone id=85388500 url=about:blank didCrash=true returns=false
F chromium: [FATAL:third_party/crashpad/crashpad/client/crashpad_client_linux.cc:763] Render process (9113)'s crash wasn't handled by all associated  webviews, triggering application crash.
F libc    : Fatal signal 5 (SIGTRAP), code 1 (TRAP_BRKPT) ... (repro.repro_app)

In the same runs, the app's live InAppWebView received onRenderProcessGone through the plugin's normal client and returned true. Out of 40 cold starts, all 32 app deaths were preceded (within 0–5 ms) by returns=false from the dispose client, and none of the 8 surviving runs had it.

Flutter version

3.44.4 (Dart 3.12.2)

Operating System, Device-specific and/or Tool

Android 16 (API 36) emulator (sdk_gphone64_arm64), Android System WebView 155.0.8059.43

Plugin version

6.2.0-beta.3 (master 17527cae), flutter_inappwebview_android 1.2.0-beta.3. The same code is in 6.2.0-beta.2.

Additional information

Self grab

  • I'm ready to work on this issue!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions