Skip to content

fix(desktop-gpui): recover from a lost GPU device on Linux without crashing in the NVIDIA driver - #3979

Merged
richiemcilroy merged 1 commit into
mainfrom
fix/linux-gpu-device-lost-recovery
Nov 9, 2026
Merged

richiemcilroy merged 1 commit into
mainfrom
fix/linux-gpu-device-lost-recovery

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Fixes #3946.

On Linux with NVIDIA and Wayland, Cap crashed with a SIGSEGV at address 0 inside the NVIDIA driver after the GPU device was lost. Before the crash its windows could go permanently blank (painted_fps=0.0 in the log).

#0  0x0000000000000000
#1  libnvidia-eglcore.so.595.112.07
#2  libnvidia-eglcore.so.595.112.07
#3  libnvidia-eglcore.so.595.112.07
#4  ash::khr::surface::get_physical_device_surface_support
#5  wgpu_hal::vulkan  surface_capabilities
#14 gpui_wgpu::WgpuRenderer::new_internal   wgpu_renderer.rs:305
#15 gpui_wgpu::WgpuRenderer::recover        wgpu_renderer.rs:2313
#16 gpui_linux  wayland window draw         window.rs:2293

Root cause

Two defects in gpui's device-lost handling on Linux.

sequenceDiagram
    participant W as window
    participant R as WgpuRenderer::recover
    participant D as NVIDIA driver
    W->>R: device lost
    R->>D: create instance B, surface, device
    R->>D: release old resources (device A and instance A destroyed)
    R->>D: surface query or swapchain creation on instance B
    D-->>W: call through a null pointer, SIGSEGV at 0
Loading
  • The crash. WgpuRenderer::recover (gpui_wgpu/src/wgpu_renderer.rs:2286) made a new wgpu instance for the new device, then released the old one. With Wayland surfaces in use, NVIDIA's Vulkan driver does not survive a second instance being created and the first destroyed: the next vkGetPhysicalDeviceSurfaceSupportKHR or vkCreateSwapchainKHR on the surviving instance calls a null pointer inside the driver. Destroying only the old device is fine, and so is the same sequence on X11.
  • The blank windows. In gpui_linux/src/linux/wayland/window.rs:2296 a frame that finds the device lost, or is spent recovering, presents nothing and relies on the next frame callback. A compositor sends frame callbacks only for a mapped surface. When that frame was the one that maps the window (a new window, or one shown again after being hidden), no callback ever came: the window stayed invisible and every later show ended in Could not restore retained window visibility.

Fix

apps/desktop-gpui/patches/zed-device-lost.patch, applied to the pinned gpui:

  • recover keeps the lost context in place until its replacement exists and creates the replacement on the same instance, so no instance is destroyed while another is in use. A failed attempt retries with that instance.
  • A draw that finds the device lost asks for a forced redraw, so the window recovers on its next frame instead of waiting for unrelated invalidation.
  • When a frame presented nothing, the surface has no buffer and a render is still owed, the window draws again after 50 ms instead of waiting for a frame callback (unmapped_frame_needs_retry, with unit tests).
  • Recovery refused software renderers so a real GPU could come back. It now accepts one when the lost device was itself software, which otherwise never recovered.
  • GPUI_INJECT_DEVICE_LOSS=<file> is a test hook: creating the file makes the renderer's next frame end as it does when the driver reports the device lost. scripts/linux-desktop-harness/scenario-device-loss.sh uses it in the Hyprland job: close the main window, lose the device, launch Cap again, and the window must come back.

Before and after

Tesla T4, NVIDIA 595.112.07 (open kernel module), Wayland, camera preview running. The device loss is injected by a test-only wgpu-hal build that returns a lost device from queue submit. Everything after that, including the segfault, is the real driver. Two runs of each, same outcome both times.

Scenario main this PR
One window, device lost no crash, window stays on the lost device until something else redraws it recovered
Main and camera windows, device lost SIGSEGV at 0 in the NVIDIA driver (trace above) both recovered, preview at 30 fps
Main window hidden, device lost, shown again no window maps again, painted_fps=0.0, later shows fail both windows back, preview at 27 fps
X11, device lost recovered recovered

The hidden-window row reproduces the log sequence in the issue: camera preview resumed, wgpu device lost: reason=Unknown, GPU device lost, recreating context..., then painted_fps=0.0.

Hyprland 0.57 on software rendering, SCENARIO=device-loss, three runs of each:

Result main with only the test hook this PR
shown_again no, no, no yes, yes, yes
recovered 0 1
restore_failed 1 0

Limits

  • The reporter's driver fault (Xid 32) cannot be produced on demand, so the device loss in every run above is injected. The crash it leads to on main is the real driver's.
  • The instance reuse has no CI test. The crash needs NVIDIA's driver, and Mesa tolerates both orderings.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable issue was established.

Summary

This PR changes Linux GPU recovery and adds a hidden-window regression scenario.

  • GPU recovery reuses the existing instance for its replacement device.
  • Wayland redraws windows that miss their first frame after device loss.
  • Hyprland CI checks that a hidden window returns after device loss.

richiemcilroy explicitly acknowledges that instance reuse has no CI test because reproducing the crash requires NVIDIA’s driver. That known limit is not reported as a finding.

Reviews (1) · Last reviewed commit: "fix(desktop-gpui): recover from a lost G..." · Reviewed by Greptile

@sandchest-com

sandchest-com Bot commented Nov 9, 2026

Copy link
Copy Markdown

Sandchest

Sandchest reviewed 131c694: nothing exploitable found in this change.

Sandchest reviews every change for vulnerabilities an attacker could use · 1 credit · Review details

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capy found no issues.

View 2 other findings in Capy.

Open in Capy

@richiemcilroy
richiemcilroy merged commit 9a83194 into main Nov 9, 2026
64 of 65 checks passed

This branch was successfully deployed

1 active deployment
Preview – cap-web — 131c6946 Deployed Nov 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux: SIGSEGV after wgpu device lost — crash path through libnvidia-glcore, NVIDIA Xid 32, camera-only mode (0.6.2)

2 participants