http://bugs.winehq.org/show_bug.cgi?id=36977
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW URL| |http://store.steampowered.c | |om/app/255420/ CC| |focht@gmx.net Component|-unknown |ole32 Summary|Magic: The Gathering – |Magic: The Gathering – |Duels of the Planeswalkers |Duels of the Planeswalkers |2015 crashes after few |2015 (Steam) crashes after |frames of intro sequence |few frames of intro | |sequence (multi-thread race | |during XAudio2 tear down) Ever confirmed|0 |1
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming, can be reproduced with the demo version as well. Steam game overlay is not the problem here.
--- snip --- $ WINEDEBUG=+tid,+seh,+relay,+snoop,+dsound wine ./steam.exe -applaunch 255440 -no-dwrite ... 006d:CALL bink2w32._BinkOpenXAudio2@4(<unknown, check return>) ret=0108e6ea 006d:Call ole32.CoInitializeEx(00000000,00000000) ret=01098d54 ... 006d:Call ole32.CoCreateInstance(010cb2ac,00000000,00000001,010cb2bc,0827d5cc) ret=0108102c ... 006d:Call KERNEL32.LoadLibraryExW(0827d16e L"C:\windows\system32\XAudio2_7.dll",00000000,00000008) ret=7e0c188c 006d:Ret KERNEL32.LoadLibraryExW() retval=08a10000 ret=7e0c188c ... 006d:CALL xaudio2.DllGetClassObject(<unknown, check return>) ret=7e0c3e99 006d:RET xaudio2.DllGetClassObject(0827d4e8,7e1b3eec,0827d4f8) retval=00000000 ret=7e0c3e99 ... 006d:Call KERNEL32.CreateThread(00000000,00000000,08a4a670,09599050,00000004,00000000) ret=08a4a372 006d:Ret KERNEL32.CreateThread() retval=0000026c ret=08a4a372 ... 0077:Starting thread proc 0x8a4a670 (arg=0x9599050) ... 006d:RET bink2w32._BinkOpenXAudio2@4(00000000) retval=01098bb0 ret=0108e6ea 006d:RET bink2w32._BinkSetSoundSystem@8(003b0363,00000000) retval=00000001 ret=008e5faf 006d:CALL bink2w32._BinkSetSoundTrack@8(<unknown, check return>) ret=008e5fc8 006d:RET bink2w32._BinkSetSoundTrack@8(00000001,11040438) retval=00000001 ret=008e5fc8 006d:CALL bink2w32._BinkSetIO@4(<unknown, check return>) ret=008e5ff2 006d:RET bink2w32._BinkSetIO@4(00b18900) retval=00b18900 ret=008e5ff2 ... 006d:RET bink2w32._BinkOpen@8(0827d884,02004400) retval=00000000 ret=008e6015 0077:trace:dsound:IDirectSoundBufferImpl_GetCurrentPosition (0x11100780,0xf2be944,0xf2be93c) ... 0077:trace:dsound:IDirectSoundBufferImpl_GetCurrentPosition playpos = 0, writepos = 1764, buflen=52920 (0x11100780, time=8160876) ... 006d:CALL bink2w32._BinkGetError@0(<unknown, check return>) ret=008e601e 006d:RET bink2w32._BinkGetError@0() retval=010c0618 ret=008e601e 006d:CALL bink2w32._BinkClose@4(<unknown, check return>) ret=004e2c51 006d:RET bink2w32._BinkClose@4(00000000) retval=0827d88c ret=004e2c51 006d:Call KERNEL32.GetLastError() ret=005abf07 006d:Ret KERNEL32.GetLastError() retval=000000cb ret=005abf07 ... 0077:trace:dsound:IDirectSoundBufferImpl_GetCurrentPosition (0x11100780,0xf2be944,0xf2be93c) ... 006d:Ret PE DLL (proc=0xf5ee4a,module=0xe90000 L"fmodex.dll",reason=THREAD_DETACH,res=(nil)) retval=1 006d:Call PE DLL (proc=0x7e1a0258,module=0x7e0a0000 L"ole32.dll",reason=THREAD_DETACH,res=(nil)) 006d:CALL xaudio2.DllCanUnloadNow(<unknown, check return>) ret=7e0c3384 006d:RET xaudio2.DllCanUnloadNow() retval=00000000 ret=7e0c3384 006d:Call KERNEL32.FreeLibrary(08a10000) ret=7e0c1c03 006d:Call PE DLL (proc=0x8a41ce5,module=0x8a10000 L"XAudio2_7.dll",reason=PROCESS_DETACH,res=(nil)) ... 006d:Ret PE DLL (proc=0x8a41ce5,module=0x8a10000 L"XAudio2_7.dll",reason=PROCESS_DETACH,res=(nil)) retval=1 ... 006d:Ret KERNEL32.FreeLibrary() retval=00000001 ret=7e0c1c03 ... 0077:Call KERNEL32.GetTickCount() ret=7d03db34 0077:Ret KERNEL32.GetTickCount() retval=007c866c ret=7d03db34 0077:trace:dsound:IDirectSoundBufferImpl_GetCurrentPosition playpos = 0, writepos = 1764, buflen=52920 (0x11100780, time=8160876) 0077:Call KERNEL32.WaitForMultipleObjects(00000003,09599068,00000000,0000000a) ret=08a4a5e0 0077:Ret KERNEL32.WaitForMultipleObjects() retval=00000102 ret=08a4a5e0 0077:trace:seh:raise_exception code=c0000005 flags=0 addr=0x8a4a5e0 ip=08a4a5e0 tid=0077 0077:trace:seh:raise_exception info[0]=00000000 0077:trace:seh:raise_exception info[1]=08a4a5e0 0077:trace:seh:raise_exception eax=00000102 ebx=7bcd1000 ecx=09599068 edx=00000000 esi=0f2bfb40 edi=003d0f00 0077:trace:seh:raise_exception ebp=0f2be988 esp=0f2be97c cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010202 0077:trace:seh:call_stack_handlers calling handler at 0x7bc9dbe3 code=c0000005 flags=0 ... Unhandled exception: page fault on read access to 0x08a4a5e0 in 32-bit code (0x08a4a5e0). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:08a4a5e0 ESP:0f2be97c EBP:0f2be988 EFLAGS:00010202( R- -- I - - - ) EAX:00000102 EBX:7bcd1000 ECX:09599068 EDX:00000000 ESI:0f2bfb40 EDI:003d0f00 ... Backtrace: =>0 0x08a4a5e0 (0x0f2be988) 1 0x08a494f0 (0x0f2bea4c) 2 0x08a4a6ab (0x0f2bea58) 3 0x7bc857e8 call_thread_func_wrapper+0xb() in ntdll (0x0f2bea68) 4 0x7bc85831 call_thread_func+0x3e(entry=0x8a4a670, arg=0x9599050, frame=0xf2beb68) [/home/focht/projects/wine/wine.repo/src/dlls/ntdll/signal_i386.c:2637] in ntdll (0x0f2beb48) 5 0x7bc857c6 call_thread_entry_point+0x11() in ntdll (0x0f2beb68) 6 0x7bc8cbce start_thread+0x11a(info=0x7ff6cfb8) [/home/focht/projects/wine/wine.repo/src/dlls/ntdll/thread.c:429] in ntdll (0x0f2bf3a8) 7 0xf75e29da start_thread+0xc9() in libpthread.so.0 (0x0f2bf468) ... 0x08a4a5e0: addb %al,0x0(%eax) Modules: Module Address Debug info Name (168 modules) PE 360000- 372000 Deferred xinput9_1_0 PE 400000- e8d000 Deferred dotp_d15 PE e90000- 1007000 Deferred fmodex PE 1010000- 107c000 Deferred fmod_event PE 1080000- 10e6000 Deferred bink2w32 PE 3a10000- 3ae3000 Deferred steam PE 3c20000- 3fe8000 Deferred d3dx9_39 PE 10000000-101ff000 Deferred d3dx9_43 PE 30000000-302c1000 Deferred steam2 PE 38000000-38893000 Deferred steamclient PE 3b400000-3b41e000 Deferred steam_api PE 3f000000-3f0b2000 Deferred tier0_s PE 3f600000-3f64f000 Deferred vstdlib_s ... Threads: process tid prio (all id:s are in hex) ... 00000058 (D) C:\Program Files\Steam\SteamApps\common\Magic 2015 Demo\DotP_D15.exe 00000077 15 <== 00000076 15 ... --- snip ---
XAudio2 is brought up by 'bink2w32._BinkOpenXAudio2' API.
RAD's Bink loads the 'XAudio2_7.dll' inproc-server which in turn creates a worker thread.
A short time later, 'XAudio2_7.dll' inproc-server gets unloaded/released ('xaudio2.DllCanUnloadNow' -> S_OK, refcount = 0) after Bink failed to load some non-existing file (by design).
The thread that owns the MTA exits, which triggers apartment destruction.
Debugger session (not the same run as trace log):
--- snip --- Wine-dbg>bt
Backtrace: =>0 0x7e0c3368 apartment_freeunusedlibraries+0x2d(apt=0x10ae24c0, delay=0) [/home/focht/projects/wine/wine.repo/src/dlls/ole32/compobj.c:1082] in ole32 (0x0740e608) 1 0x7e0c386d apartment_release+0x3df(apt=0x10ae24c0) [/home/focht/projects/wine/wine.repo/src/dlls/ole32/compobj.c:1194] in ole32 (0x0740e6a8)
...
7 0x7bc58f1b LdrShutdownThread+0xee() [/home/focht/projects/wine/wine.repo/src/dlls/ntdll/loader.c:2592] in ntdll (0x0740e998) 8 0x7bc8d268 exit_thread+0xb1(status=0) [/home/focht/projects/wine/wine.repo/src/dlls/ntdll/thread.c:378] in ntdll (0x0740ea58) 9 0x7bc86071 call_thread_func_wrapper+0x14() in ntdll (0x0740ea68)
Wine-dbg>p *entry
{entry={next=0x10d29d48, prev=0x10ae251c}, dll=0xcce9770, unload_time=0, multi_threaded=0x1}
Wine-dbg>p *entry->dll
{refs=0x1, library_name="C:\windows\system32\XAudio2_7.dll", library=0x7520000, DllGetClassObject=0x7551150, DllCanUnloadNow=0x7550aa0, entry={next=0x7e1f3ba0, prev=0x5da2ac4}} --- snip ---
The XAudio2 worker thread is still alive at this point. Upon return from 'WaitForMultipleObjects' due to 'WAIT_TIMEOUT' (see log), the thread resumes execution on a page that is no longer there because dll was unmapped earlier, causing the crash.
Wine already tries to handle races with object destruction vs. thread shutdown.
http://source.winehq.org/git/wine.git/blob/efdaa4a17a4a2582123e83da80a03f401...
--- snip --- 1076 static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay) 1077 { 1078 struct apartment_loaded_dll *entry, *next; 1079 EnterCriticalSection(&apt->cs); 1080 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry) 1081 { 1082 if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) 1083 { 1084 DWORD real_delay = delay; 1085 1086 if (real_delay == INFINITE) 1087 { 1088 /* DLLs that return multi-threaded objects aren't unloaded 1089 * straight away to cope for programs that have races between 1090 * last object destruction and threads in the DLLs that haven't 1091 * finished, despite DllCanUnloadNow returning S_OK */ 1092 if (entry->multi_threaded) 1093 real_delay = 10 * 60 * 1000; /* 10 minutes */ 1094 else 1095 real_delay = 0; 1096 } 1097 1098 if (!real_delay || (entry->unload_time && ((int)(GetTickCount() - entry->unload_time) > 0))) 1099 { 1100 list_remove(&entry->entry); 1101 COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); 1102 HeapFree(GetProcessHeap(), 0, entry); 1103 } 1104 else 1105 { 1106 entry->unload_time = GetTickCount() + real_delay; 1107 if (!entry->unload_time) entry->unload_time = 1; 1108 } 1109 } 1110 else if (entry->unload_time) 1111 entry->unload_time = 0; 1112 } 1113 LeaveCriticalSection(&apt->cs); 1114 } --- snip ---
'apartment_release' passes zero delay, causing immediate unload. A small delay prevents this but this is obviously a hack to work around broken behaviour.
This can also be worked around by disabling 'XAudio2_7.dll' via 'winecfg'.
Regards