QEMULauncher crashes with EXC_GUARD / __darwin_check_fd_set_overflow in g_poll when fd numbers exceed 1024
- Dominant language
- Swift
- Stars
- 35.5k
- Forks
- 1.8k
- Avg merge
- 5d 5h
- Merged PRs (30d)
- 7
Description
## Description
QEMULauncher crashes repeatedly with `EXC_GUARD` triggered by `__darwin_check_fd_set_overflow` inside GLib's `g_poll()`. The crash occurs because QEMU's main event loop uses `select()` (via `g_poll`), which has a hard compile-time limit of `FD_SETSIZE = 1024`. When any open file descriptor has a number ≥ 1024, macOS kills the process with an `EXC_GUARD` exception.
## Environment
- **UTM version**: 4.7.5 (build 118)
- **macOS version**: macOS 26.3 (25D125)
- **Hardware**: Mac mini, Apple M4 Pro, 64 GB RAM
- **VM architecture**: aarch64
- **VM config**: Ubuntu 22.04, 4 vCPUs, 12 GB RAM, `virtio-gpu-gl-pci` display, HVF acceleration
## Crash Details
- **Exception**: `EXC_GUARD / GUARD_TYPE_USER`
- **Termination**: `LIBSYSTEM — Application Triggered Fault`
- **Message**: `namespc 18 reason_code 0x0000000000000002`
**Faulting thread stack trace:**
```
#0 os_fault_with_payload +8
#1 __darwin_check_fd_set_overflow +212 ← macOS guard kills process here
#2 g_poll +236
#3 main_loop_wait +340
#4 qemu_main_loop +96
#5 start +7184
```
## Reproduction
The VM runs fine initially but crashes after accumulating enough open file descriptors with **numbers** (not just count) exceeding 1023. With `virtio-gpu-gl-pci` + `gl=on` in SPICE, multiple persistent rendering channels push fd numbers above 1024 within minutes. Crashed 5 times across two days, always with the identical stack trace.
Inspecting the live QEMU process with `lsof` showed a large cluster of `IPv4 (CLOSED)` sockets in the fd number range 1000–1103, keeping high fd slot numbers permanently occupied.
## Workaround
In `config.plist`, change the display hardware from `virtio-gpu-gl-pci` to `virtio-gpu-pci`. This reduces fd pressure and stabilizes the max fd at ~1019, but does not fully eliminate the risk for long sessions since the limit is still only 5 away.
## Root Cause
GLib's `g_poll()` on macOS falls back to `select()`, bounded by `FD_SETSIZE = 1024` (compile-time constant). When QEMU passes any fd ≥ 1024 to `select()`, macOS' `__darwin_check_fd_set_overflow` guard fires `EXC_GUARD` and terminates the process.
## Suggested Fix
Replace `g_poll()` / `select()` in QEMU's main event loop with `poll()` or `kqueue`, which have no fd number limit. Alternatively, reduce the number of persistent SPICE channel fds opened by `virtio-gpu-gl-pci`.
Contributor guide
Assessment
This issue has not been assessed yet.