-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Description
While retesting #4915, I discovered that WGI initialization now deterministically fails (since 8ebef12) unless the application calls CoInitializeEx(NULL, COINIT_MULTITHREADED)
prior to initializing the joystick stubsystem.
Our RoInitialize()
call fails due to incompatible concurrency model (RPC_E_CHANGED_MODE
) with a previous CoInitializeEx()
call.
The first call to CoInitializeEx()
comes from DirectInput:
# Child-SP RetAddr Call Site
00 000000c8`dcbef458 00007ff9`92968059 SDL2!WIN_CoInitialize [C:\Users\camer\SDL\src\core\windows\SDL_windows.c @ 86]
01 000000c8`dcbef460 00007ff9`92970dd9 SDL2!SDL_DINPUT_JoystickInit+0x9 [C:\Users\camer\SDL\src\joystick\windows\SDL_dinputjoystick.c @ 400]
02 000000c8`dcbef4b0 00007ff9`929628f3 SDL2!WINDOWS_JoystickInit+0x9 [C:\Users\camer\SDL\src\joystick\windows\SDL_windowsjoystick.c @ 442]
03 000000c8`dcbef4e0 00007ff9`92a0f4c8 SDL2!SDL_JoystickInit+0x83 [C:\Users\camer\SDL\src\joystick\SDL_joystick.c @ 247]
04 000000c8`dcbef520 00007ff9`92910002 SDL2!SDL_InitSubSystem_REAL+0x198 [C:\Users\camer\SDL\src\SDL.c @ 260]
05 000000c8`dcbef560 00007ff7`b13a17ba SDL2!SDL_InitSubSystem+0x12 [C:\Users\camer\SDL\src\dynapi\SDL_dynapi_procs.h @ 86]
06 000000c8`dcbef590 00007ff7`b13a1d19 JoystickCrashTest!main+0x2a [C:\Users\camer\source\repos\JoystickCrashTest\JoystickCrashTest.cpp @ 15]
07 000000c8`dcbef6c0 00007ff7`b13a1bbe JoystickCrashTest!invoke_main+0x39 [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79]
08 000000c8`dcbef710 00007ff7`b13a1a7e JoystickCrashTest!__scrt_common_main_seh+0x12e [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
09 000000c8`dcbef780 00007ff7`b13a1dae JoystickCrashTest!__scrt_common_main+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
0a 000000c8`dcbef7b0 00007ffa`6eed54e0 JoystickCrashTest!mainCRTStartup+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
0b 000000c8`dcbef7e0 00007ffa`6f76485b KERNEL32!BaseThreadInitThunk+0x10
0c 000000c8`dcbef810 00000000`00000000 ntdll!RtlUserThreadStart+0x2b
WIN_CoInitialize()
tries to use an apartment threading model if COM is not already initialized:
/* SDL handles any threading model, so initialize with the default, which
is compatible with OLE and if that doesn't work, try multi-threaded mode.
If you need multi-threaded mode, call CoInitializeEx() before SDL_Init()
*/
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (hr == RPC_E_CHANGED_MODE) {
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
So we will end up with apartment threading unless the application has already initialized COM outside of SDL.
Next we will try to call RoInitialize(RO_INIT_MULTITHREADED)
, which is a conflicting concurrency model with apartment threading that we used earlier.
# Child-SP RetAddr Call Site
00 000000c8`dcbef448 00007ff9`9297250e SDL2!WIN_RoInitialize [C:\Users\camer\SDL\src\core\windows\SDL_windows.c @ 144]
01 000000c8`dcbef450 00007ff9`929628f3 SDL2!WGI_JoystickInit+0x1e [C:\Users\camer\SDL\src\joystick\windows\SDL_windows_gaming_input.c @ 443]
02 000000c8`dcbef4e0 00007ff9`92a0f4c8 SDL2!SDL_JoystickInit+0x83 [C:\Users\camer\SDL\src\joystick\SDL_joystick.c @ 247]
03 000000c8`dcbef520 00007ff9`92910002 SDL2!SDL_InitSubSystem_REAL+0x198 [C:\Users\camer\SDL\src\SDL.c @ 260]
04 000000c8`dcbef560 00007ff7`b13a17ba SDL2!SDL_InitSubSystem+0x12 [C:\Users\camer\SDL\src\dynapi\SDL_dynapi_procs.h @ 86]
05 000000c8`dcbef590 00007ff7`b13a1d19 JoystickCrashTest!main+0x2a [C:\Users\camer\source\repos\JoystickCrashTest\JoystickCrashTest.cpp @ 15]
06 000000c8`dcbef6c0 00007ff7`b13a1bbe JoystickCrashTest!invoke_main+0x39 [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79]
07 000000c8`dcbef710 00007ff7`b13a1a7e JoystickCrashTest!__scrt_common_main_seh+0x12e [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
08 000000c8`dcbef780 00007ff7`b13a1dae JoystickCrashTest!__scrt_common_main+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
09 000000c8`dcbef7b0 00007ffa`6eed54e0 JoystickCrashTest!mainCRTStartup+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
0a 000000c8`dcbef7e0 00007ffa`6f76485b KERNEL32!BaseThreadInitThunk+0x10
0b 000000c8`dcbef810 00000000`00000000 ntdll!RtlUserThreadStart+0x2b
This fails with RPC_E_CHANGED_MODE
and causes us to fail to initialize the WGI joystick driver. It looks like RO_INIT_SINGLETHREADED
is equivalent to COINIT_APARTMENTTHREADED
, so we should probably try that like WIN_CoInitialize()
does.