Hello @aydar-kamaltdinov, we're using one issue report per unofficially supported game title, and usually I'd transfer this issue report to #279, however, at no point did Proton 10 support ARM based builds or any running on Android. Esync based thread synchronization is also being phased out in favor of ntsync.
Closing as invalid.
proton 10.0x1 2026-08PROTON_LOGx1 2026-08WINEESYNC=0x1 2026-08WINEESYNC=1x1 2026-08WINEESYNC=1`x1 2026-08
Compatibility Report
System Information
proton_10.0branch, commitb8fdff8e1f855b5276ec4ddca0f31b2792554322I confirm:
Note on scope: this was originally found on Android (a Proton-derived ARM64EC build used by several "run Windows games on Android" apps), not on desktop Linux/Steam Deck — so the usual GPU/driver/kernel/PROTON_LOG fields don't apply in the normal sense. However, the root cause is a
wineserver-side file descriptor leak, entirely independent of GPU/rendering/platform, and I've directly confirmed the same buggy code is present in this repository's ownproton_10.0branch (not just a downstream fork), so it should reproduce identically on desktop Proton/Steam Deck under the same conditions (see Reproduction below) — same root cause, same fix.Symptoms
The game crashes deterministically with
EXCEPTION_ACCESS_VIOLATIONafter a fixed number of simulation ticks (~14400, i.e. after a fixed amount of active gameplay time, not real time — confirmed independent of framerate). Root cause:WINEESYNC=1leaks exactly one real file descriptor (thread->esync_apc_fd) perCreateThread(), for the lifetime ofwineserver— deterministically, on every thread, even with fully correct application code (CreateThread+WaitForSingleObject+CloseHandle). A game/engine that spawns one short-lived worker thread per simulation tick (common — job systems, audio callbacks, etc.) will hitRLIMIT_NOFILEafter a fixed, predictable number of ticks. Invisible on real Windows (near-unlimited handle table), fatal here.Root cause detail
server/thread.c,create_thread()allocates two eventfds per thread object:esync_apc_fd is referenced elsewhere only via esync_wake_fd() / esync_clear() (APC signaling) — never close()d anywhere in the tree. Note the fsync path right below correctly frees both fsync_idx and fsync_apc_idx — this looks like a straightforward oversight specific to the esync side only.
Fix
Empirical verification
Built
wineserverfrom this repo'sproton_10.0branch foraarch64-linux-android(NDK r29) to match the exact protocol version (856) used by the realdevice build. Ran a 200-iteration
CreateThreadloop, measuringwineserver's live eventfd count via/proc/<pid>/fd:Scenario: 200x CreateThread WITHOUT CloseHandle
Before fix: 852 (baseline ~452 + 200x2)
After fix: 853 (unchanged -- object never destroyed, expected)
Scenario: 200x CreateThread WITH CloseHandle (correct app code)
Before fix: 652 (baseline ~452 + 200x1 -- leaking despite fully correct code)
After fix: 453 (= baseline, ZERO leak)
Reproduction
Also filed upstream against WineHQ (original home of the eventfd_synchronization patchset, since removed from wine-staging master in favor of ntsync): https://bugs.winehq.org/show_bug.cgi?id=60215
Note: this report was drafted/formatted with AI assistance for the technical writeup, but all testing, reproduction, log capture, root-causing, and the empirical before/after fix verification (attaching to the process's fd table, building and cross-compiling Wine from source, confirming protocol-version-exact compatibility with a real device build) were performed and manually confirmed by me on physical hardware.