Skip to content

Android: SIGSEGV in dawn::native::vulkan::FencedDeleter::DeleteWhenUnused when a Canvas unmounts (Surface::~Surface via onDropViewInstance) #468

Description

@eduardoborges

Version: react-native-webgpu 0.9.0, three 0.184.0 (WebGPURenderer), React Native 0.87.1 (New Architecture, Hermes), react-native-reanimated 4.6.0 / react-native-worklets 0.12.1.

Device: Android emulator Pixel_10 (API 37, arm64, -gpu host, Vulkan ranchu), NDK 27.1, minSdk 26.

What happens

A screen with one <Canvas transparent /> renders a glTF with three's WebGPURenderer (render loop via setAnimationLoop, context.present() each frame). Rendering, textures and gestures work. When the screen is popped (React Navigation native-stack) and the Canvas unmounts, the app dies with a native crash in roughly 2 out of 3 unmounts:

F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x20
  dawn::native::vulkan::FencedDeleter::DeleteWhenUnused
  dawn::native::vulkan::SwapChain::DetachFromSurfaceImpl
  dawn::native::Surface::~Surface
  com.webgpu.WebGPUView.destroy
  com.webgpu.WebGPUViewManager.onDropViewInstance

The crash happens 0.1 s to 0.4 s after the React effect cleanup runs. In some runs it is preceded by I WebGPU: GPU Device Lost (Destroyed): Device was destroyed., in others there is no device-lost line at all. iOS (Metal) never crashes with the same code.

What I tried from JS, none of it changes the outcome

  1. renderer.setAnimationLoop(null) then renderer.dispose() in the effect cleanup (baseline): crash 3/3.
  2. Same plus context.unconfigure() before dispose (confirmed it executes): crash 2/3.
  3. Same plus keeping a strong reference to the renderer (and therefore the GPUDevice) for 3 s after unmount, so the device cannot be collected before the native view is dropped: crash 2/3, with no "Device Lost" line, so the device was alive when Surface::~Surface ran.

Timeline of one crash (logcat, -v time), with console.warn markers from JS:

14:40:52.887 W/ReactNativeJS: MedalShowcase: cleanup start
14:40:53.312 F/libc: Fatal signal 11 (SIGSEGV) ... fault addr 0x20

Where I think it is

SurfaceInfo::~SurfaceInfo (cpp/rnwgpu/SurfaceRegistry.h) releases _surface and _pendingSurface before _texture, and it runs on the UI thread from onDropViewInstance while the JS side may still be tearing the renderer down. If a swapchain texture is still alive, or a frame is still in flight, Dawn's Vulkan swapchain detaches against state that is already gone. unconfigure() from JS only touches _surface, not _pendingSurface, which would explain why it does not help when a pending attach exists.

Repro

Any screen that mounts a Canvas, renders one frame with three's WebGPURenderer, and is popped. A minimal version is the three.js sample from the docs inside a native-stack screen; navigate in, wait for the first frame, press back, repeat a few times.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions