[Bug 36977] Magic:=?UTF-8?Q?=20The=20Gathering=20=E2=80=93=20Duels=20of=20the=20Planeswalkers=202015=20?=(Steam) crashes after few frames of intro sequence (multi-thread race during XAudio2 tear down)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Jul 26 17:39:21 CDT 2014


http://bugs.winehq.org/show_bug.cgi?id=36977

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
                URL|                            |http://store.steampowered.c
                   |                            |om/app/255420/
                 CC|                            |focht at 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 at 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 at 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 at 4(00000000) retval=01098bb0 ret=0108e6ea
006d:RET  bink2w32._BinkSetSoundSystem at 8(003b0363,00000000) retval=00000001
ret=008e5faf
006d:CALL bink2w32._BinkSetSoundTrack at 8(<unknown, check return>) ret=008e5fc8
006d:RET  bink2w32._BinkSetSoundTrack at 8(00000001,11040438) retval=00000001
ret=008e5fc8
006d:CALL bink2w32._BinkSetIO at 4(<unknown, check return>) ret=008e5ff2
006d:RET  bink2w32._BinkSetIO at 4(00b18900) retval=00b18900 ret=008e5ff2
...
006d:RET  bink2w32._BinkOpen at 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 at 0(<unknown, check return>) ret=008e601e
006d:RET  bink2w32._BinkGetError at 0() retval=010c0618 ret=008e601e
006d:CALL bink2w32._BinkClose at 4(<unknown, check return>) ret=004e2c51
006d:RET  bink2w32._BinkClose at 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/efdaa4a17a4a2582123e83da80a03f401e8146e4:/dlls/ole32/compobj.c#l1076

--- 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

-- 
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.


More information about the wine-bugs mailing list