Skip to content

WGI initialization fails on Win32 #5552

@cgutman

Description

@cgutman

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions