[Bug 60212] New: EmEditor 20.6.1: crashes after about a day of use with "alloc_user_handle: Assertion `index < MAX_USER_HANDLES' failed" (leaks a USER handle on every mouse move)
http://bugs.winehq.org/show_bug.cgi?id=60212 Bug ID: 60212 Summary: EmEditor 20.6.1: crashes after about a day of use with "alloc_user_handle: Assertion `index < MAX_USER_HANDLES' failed" (leaks a USER handle on every mouse move) Product: Wine Version: 11.16 Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: user32 Assignee: wine-bugs@list.winehq.org Reporter: tnatkinn@gmail.com Target Milestone: --- Distribution: --- Created attachment 81914 --> http://bugs.winehq.org/attachment.cgi?id=81914 Bug repro code EmEditor 20.6.1 (64-bit text editor) aborts after a day or so of normal editing; the terminal shows ../wine/dlls/win32u/window.c:98: alloc_user_handle: Assertion `index < MAX_USER_HANDLES' failed. and wineserver crashes right afterwards (filed separately as bug #XXXXX, it is a different problem). Cause: EmEditor loads its resource DLL emedres.dll with LOAD_LIBRARY_AS_IMAGE_RESOURCE and calls LoadCursorW(hResDll, id) + SetCursor() on every WM_SETCURSOR. In Wine each of these LoadCursorW calls returns a *new* cursor handle (on Windows LoadCursor returns the same shared handle every time and the app correctly never destroys it), so the process leaks one USER handle per mouse move (~150/s while the mouse moves) until the session's user handle table is full. Why: dlls/user32/cursoricon.c CURSORICON_Load() only consults the shared cursor/icon cache when LdrGetDllFullName(hInstance) succeeds. It fails for handles of modules loaded with LOAD_LIBRARY_AS_DATAFILE / LOAD_LIBRARY_AS_IMAGE_RESOURCE (low bits set, not a loader module), so the lookup is skipped and a new cursor object is created every time (the module name is also missing when the object is recorded, so it can never be found later). Standalone test case attached (cursorleak.c + test.rc + test.cur, build with mingw-w64; source only). It loads a copy of itself with each LOAD_LIBRARY_AS_* flag and calls LoadCursorW 1000 times: normal module : 0 of 1000 calls returned a NEW handle (ok) LOAD_LIBRARY_AS_IMAGE_RESOURCE: 1000 of 1000 calls returned a NEW handle (LEAK) LOAD_LIBRARY_AS_DATAFILE : 1000 of 1000 calls returned a NEW handle (LEAK) With "cursorleak.exe 40000" the assert above is hit (and wineserver crashes, see the other bug). Tested with wine-11.15 (distro package) and wine-11.16 built from git, clean 64-bit ~/.wine, no DLL overrides, CachyOS Linux (Arch-based) x86-64, KDE Plasma/Wayland (XWayland). First noticed under CrossOver 26.3 (same Wine code, same behaviour). A patch (user32 fix + conformance test in user32/tests/cursoricon.c, tested on wine-11.16: cursoricon 0 failures, test case 0 leaked handles) is attached. Download: EmEditor 20.6.1 64-bit, https://www.emeditor.com/download/older-versions/ emeditor-professional-20-6-1-64bit.msi sha1 c970f1414f5d2896fc839f688bf8a67f14de210b (runs as free/trial without a license). Reproduce: open any file, move the mouse over the text for a while; watch the USER handle count (see attached monitor_handles.py which reads the wineserver session shared memory) or just wait for the assert. Attachments (text/plain unless noted; bundled in bug1-attachments.tar.gz): cursorleak.c, test.rc, test.cur (test case source) — keyword testcase cursorleak-output.txt (terminal output of the test case, wine-11.15 / 11.16) emeditor-terminal-output.txt (EmEditor +relay,+cursor excerpt showing the leak, one WM_SETCURSOR) 0001-user32-tests-...patch, 0002-user32-Share-cursors-...patch — keyword patch monitor_handles.py (optional helper to watch USER handle counts) -- 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.
participants (1)
-
WineHQ Bugzilla