Two top-level WebViews (one playing DRM video) — shared renderer dies on transitions. Expected or bug?

Environment: Vega SDK 0.22.6759

Setup: A React Native app renders two top-level @amazon-devices/webview instances as siblings:

  1. a lightweight menu/navigation web app with no media playback (used to switch between streams), and
  2. a video player web app using hls.js + Widevine EME to play L1/CENC DRM streams (DRM handled by the WebView’s Chromium CDM, not the native media pipeline).

We show one at a time and swap between them (menu ↔ video).

How we switch: The menu WebView stays mounted and is toggled with display:none. The player WebView is unmounted (removed from the React tree) when hidden and mounted when shown, and a stream change remounts it (via a React key) to get a clean player instance. So each menu↔video toggle and each stream switch tears down and/or recreates the DRM/EME WebView. (We also tried keeping it mounted and hiding it via opacity:0 / off-screen to avoid the teardown — see below — but those don’t hide it correctly.)

What works: both WebViews coexist and render; the player plays Widevine DRM incl. L1; steady-state playback is stable.

What fails: transitioning between the two WebViews — switching the playing stream, or toggling menu↔video — intermittently kills the renderer, and the app then aborts (SIGTRAP) with:

FATAL:kepler_common/content/browser/renderer_kill_event_observer.cc:32]
  RendererService died, killing browser process

preceded by:

WARNING:...child_process_launcher_helper_kepler_single_renderer.cc:71]
  Stopping rendererService, but its not needed because AIPC conn is already closed

It often succeeds a few times before dying, suggesting resource accumulation.

Crashing-thread backtrace (symbolicated):

#0  logging::LogMessage::HandleFatal(...)        libkepler_slatium.so
#1  logging::LogMessage::Flush()                 libkepler_slatium.so
#2  logging::LogMessageFatal::~LogMessageFatal() libkepler_slatium.so
#3  ??                                           libkepler_webview.so   ← FATAL raised here
#4–#11 ??                                        libkepler_slatium.so   (stripped Chromium frames)
#12 orpheus::framework::async::onMsgCb(...)      libasync.so.0
#13 aceAsyncLoop_run()                           libasync.so.0
#14–#17 stem_init_main_c (+ frames)              libstem_init.so

We also can’t cleanly hide one WebView while the other keeps playing: opacity:0 doesn’t hide the surface (it keeps compositing on top); display:none/unmount crashes while EME is active; moving it off-screen leaves the previously-occluded player’s video surface black on return.

Questions:

  1. Is running two top-level WebViews, one with an active DRM/EME video pipeline, a supported configuration on Kepler? Is the single shared renderer expected to remain stable under this load?
  2. Is the renderer death on stream switch / WebView swap a known issue, and is it addressed in a newer SDK/OS build?
  3. We currently unmount/remount the player WebView on hide and on stream switch. Is that the wrong approach for a DRM WebView on a shared renderer? Is there a supported way to keep the WebView alive and just hide/detach it (a WebView equivalent of native surface detach/attach), rather than tearing it down? Relatedly, is opacity/off-screen expected to hide a WebView surface, or is that unsupported for GPU-composited surfaces?
  4. Any guidance on releasing renderer resources between DRM stream loads to avoid accumulation?

Hi @ScottW ,

Thank you for the detailed write-up - the environment info, reproduction steps, backtrace, and the different approaches you’ve tried are all extremely helpful for our investigation.

Our team is looking into it and will provide an update as soon as we have more information.

Thanks for helping us improve the Vega platform.

Warm regards,
Aishwarya