microsoft / microsoft/playwright
[Bug]: Linux WebKit compositor SIGSEGV when closing a nested Base UI drawer (standalone reproduction)
- Dominant language
- TypeScript
- Stars
- 96.3k
- Forks
- 6.5k
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 180
Description
## Reproducer
[Exact tested standalone source, pinned lockfile, run instructions and SHA-256 manifest](https://github.com/m0dded/webkit-nested-drawer-repro/tree/b4f5848c4e9e209d7bf986616ca8faa619b90ca5). [Download ZIP](https://github.com/m0dded/webkit-nested-drawer-repro/archive/b4f5848c4e9e209d7bf986616ca8faa619b90ca5.zip).
## Summary
On Linux WebKit in the official `mcr.microsoft.com/playwright` images (native amd64, no GPU), closing a nested Base UI `Drawer` inside another `Drawer`'s popup at a phone viewport (`iPhone 15` device descriptor) intermittently crashes the web-content process on its compositor thread with a null object read. In the originating application, protocol logging reports `Target.targetDestroyed {crashed:true}`; a `locator.click()` on a button in the outer drawer rejects with `TargetClosedError` while waiting for the element to be stable. The launcher process later exits 0, so `DEBUG=pw:browser` alone does not show the child crash.
## Standalone reproduction (this package, Playwright 1.63.0 / WebKit 26.6 build 2359)
Vite + React 19.2.8, `@base-ui/react` 1.6.0, the shadcn `drawer.tsx` wrapper verbatim, Tailwind 4.3.3, `@playwright/test` 1.63.0, pinned lockfile. One container command (see the linked README). Test: open outer drawer → open inner drawer → "Go back" (closes inner) → click "Submit" in the outer drawer → expect outer hidden. One worker, no retries, new context per test.
| Server | Repetitions | Outcome |
|---|---|---|
| `vite preview` (production build) | 40 | all passed, 0 kernel segfaults |
| `vite preview` (production build) | 120 | all passed, 0 kernel segfaults |
| `vite` dev server | 120 | 118 passed, 2 failed (repetitions 46, 65), 2 kernel segfaults, 2 cores |
Both failures: `locator.click` on Submit → "element is not stable" retries → `Target page, context or browser has been closed`; kernel `eadedCompositor[…]: segfault at 0 ip … error 4 in libWPEWebKit-2.0.so.1.12.0[60a0f8a,…]`. Only the dev-server setting reproduced; no explanation for the difference is claimed.
## Native signature (from the originating application's runs, both builds)
- WebKit 26.5 build 2311 (Playwright 1.61.1): `libWPEWebKit-2.0.so.1.10.2` offset `0x5ec36ca`
- WebKit 26.6 build 2359 (Playwright 1.63.0): `libWPEWebKit-2.0.so.1.12.0` offset `0x60a0f8a`
Same faulting instruction `mov (%rdi),%rax` with `rdi=0` (also `rbp=0`, `r14=0`), immediately before an indirect call at vtable offset `0x40`. The surrounding 115-byte routine is byte-identical across the builds except for relocation operands. Thread name `ThreadedCompositor`. Symbols are stripped; no function name is claimed.
## Historical observations in the originating application (Next.js dev server, same drawer wrapper)
Individual runs, each a single observation, on 1.63.0 unless noted: full 185-test WebKit shard failed on this flow once on 1.61.1 and once on 1.63.0 (three other full-shard runs on 1.63.0 passed); a 40-copy loop of the application flow failed at repetitions 11, 12, 6 (three fresh runs); a 40-copy loop of an in-app harness page with only the drawer and button primitives failed at repetition 30.
## Settings tested that did not prevent the fault (application loop, 1.63.0)
Each value was injected into the isolated test environment and confirmed present in every web-content process's environment. Delivery is proven; effective use inside WebKit was confirmed only for the CPU-rendering switch (worker threads renamed `SkiaCPUWorker`). Presence in the shipped build-2359 library (`libWPEWebKit-2.0.so.1.12.0`, SHA-256 prefix `830ab277f4de888a`): `WEBKIT_SKIA_ENABLE_CPU_RENDERING`, `WEBKIT_DISABLE_DMABUF_ATLAS`, `WEBKIT_FORCE_VBLANK_TIMER`, `WEBKIT_DISPLAY_REFRESH_THROTTLE_FPS` are present; `WEBKIT_USE_SKIA_FOR_COMPOSITION` is **absent** from build 2359 (it is present in build 2311), so that arm was an inert control on the build it ran against and is listed for completeness only.
- `WEBKIT_SKIA_ENABLE_CPU_RENDERING=1`
- `WEBKIT_USE_SKIA_FOR_COMPOSITION=1`
- `WEBKIT_DISABLE_DMABUF_ATLAS=1`
- `WEBKIT_FORCE_VBLANK_TIMER=1`
- `WEBKIT_DISPLAY_REFRESH_THROTTLE_FPS=30`
Also observed in the application loops: replacing the final click with visibility polling still crashed, and the inner drawer never finished closing before the process died; a fresh container with no preceding workload still crashed; in the sampled runs cgroup OOM counters were 0 and persistent browser RSS did not grow monotonically (the standalone package does not collect memory samples).
## Environment
Docker on x86_64 Linux, 2 GiB `/dev/shm`, no GPU (each page logs `libEGL … failed to create dri2 screen` and `ZINK: vkCreateInstance failed (VK_ERROR_INCOMPATIBLE_DRIVER)`). On 1.61.1 the application shard additionally showed exit-time faults (`SkiaGPUWorker` / compositor, unmapped-code, during `exit → libEGL → dlclose`) in 55 of 185 web-content processes in one run; those were absent in the sampled 1.63.0 runs. Reported for context only; not claimed as related.
## Expected behavior
Closing the nested drawer and submitting the outer drawer should complete without crashing the web-content process.
Physical iPhone Safari has not yet been checked; this report establishes a Linux WebKit reproduction independent of the originating application. Raw application traces and cores are omitted to avoid disclosing application data.
Contributor guide
Assessment
This issue has not been assessed yet.