-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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-pcidisplay, 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.