http://bugs.winehq.org/show_bug.cgi?id=60215 Bug ID: 60215 Summary: esync: eventfd() exhaustion (EMFILE) on sync object creation not handled gracefully, propagates as guest null-pointer crash Product: Wine Version: unspecified Hardware: arm OS: Android Status: UNCONFIRMED Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@list.winehq.org Reporter: aydar.kamaltdinov@gmail.com Target Milestone: --- Note: this report was drafted/formatted with AI assistance (for structuring the technical writeup), but all testing, reproduction, log capture, and root-causing (attaching to the process's stderr, extracting the fault address/backtrace, confirming the WINEESYNC=0 workaround across multiple real runs) was done by me personally on physical hardware. Happy to answer follow-up questions or provide additional logs/raw captures directly. Possibly the same root cause as bug 58059 (eventfd leak in wineserver on thread create/destroy with WINEESYNC=1, UNCONFIRMED since 2025-04-04) — filing separately since I have a different real-world reproduction with more diagnostic detail (exact crash address + confirmed workaround), in case it helps unstick triage either way. Feel free to merge/dup if appropriate. ## Summary When WINEESYNC=1 is active and a running application leaks Windows synchronization objects (Events/Semaphores/etc.) faster than it releases them, esync's eventfd()-per-object model eventually exhausts the process's RLIMIT_NOFILE. At that point eventfd() creation fails with EMFILE, but the failure does not appear to be surfaced/handled in a way that prevents the guest application from later dereferencing an invalid/null handle — resulting in a hard crash (EXCEPTION_ACCESS_VIOLATION) instead of a recoverable API-level failure. This is architecture-independent in principle, but is far easier to trigger on platforms with a low default RLIMIT_NOFILE (e.g. Android, ~32768 in my case) than on typical desktop Linux, where the same underlying handle leak in the application would likely go unnoticed for a very long time (or indefinitely, given Windows' much larger practical handle-table ceiling). ## Observed on - A wine-staging-derived ARM64EC/WOW64 fork (used by several Android "run Windows games" projects — built from a "wine-proton-ec" tree, Proton 10.0 base), running on ARM64 Android via FEX-Emu as the WOW64 CPU backend. - I was not able to test on a vanilla x86-64 desktop Wine+wine-staging build to confirm the exact same code path applies verbatim, but the esync eventfd-creation code itself (dlls/ntdll/esync.c) appears architecture-independent, so I believe this is worth tracking upstream regardless of the specific fork. ## Reproduction case Game: Thief (2014), Steam AppID 239160, `Shipping-ThiefGame.exe`. Crashes deterministically (100% reproducible, identical fault address and full backtrace across repeated runs) during active gameplay with `WINEESYNC=1`. Captured via `WINEDEBUG=+seh,+exception`: code=c0000005 (EXCEPTION_ACCESS_VIOLATION) addr=000000014011F9D9 rip=000000014011f9d9 rcx=0000000000000000 ... Shipping-ThiefGame.exe+0x11F9D6: movq (%rbx), %rcx ; load object pointer Shipping-ThiefGame.exe+0x11F9D9: movq (%rcx), %rax <-- FAULT: rcx == 0 Shipping-ThiefGame.exe+0x11F9DC: callq *0x18(%rax) ; virtual call through vtable One capture shows this immediately preceding the crash: eventfd: Too many open files Setting `WINEESYNC=0` for this title eliminates the crash entirely (23+ minutes of gameplay with no crash, vs. a deterministic crash within minutes with esync on). ## Ask Is there existing handling in esync's object-creation path (CreateEvent/CreateSemaphore/etc. server calls) for eventfd() returning EMFILE? If not, would a graceful fallback (e.g. falling back to the non-esync/server-based wait object implementation for that single object, or returning a proper NT status the app is expected to check) be feasible, rather than leaving a handle in a state that leads to guest-side null dereferences? Happy to provide the full captured trace/disassembly if useful. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.