MongoDB can deadlock on Windows during startup due to BCryptOpenAlgorithmProvider being called from global variable constructors and thread_local variable initializers. This manifests as a rarely-occuring hang at startup.
The deadlock involves two threads and a circular dependency between bcrypt's internal critical section and the Windows loader's work queue drain
mechanism (LdrpDrainWorkQueue).
Thread A (static initialization):
ucrtbase!initterm
...
→ BCryptOpenAlgorithmProvider ← acquires bcrypt's internal CS
→ LoadLibraryExW (loading DLL)
→ LdrpLoadDllInternal
→ LdrpDrainWorkQueue ← BLOCKED waiting for Thread B
→ NtWaitForSingleObject
Thread B (new thread, thread local storage initialization):
LdrInitializeThunk
→ LdrpInitializeThread
→ LdrpCallTlsInitializers
→ ImageTlsCallbackCaller
→ PseudoRandom constructor (via thread_local SecureRandom().nextInt64())
→ BCryptOpenAlgorithmProvider
→ LoadProviderEx ← BLOCKED on bcrypt's internal CS (held by Thread A)
→ RtlEnterCriticalSection
The cycle: Thread A holds bcrypt's CS and waits for LdrpDrainWorkQueue to drain, which requires Thread B's LdrpInitializeThread to complete.
Thread B cannot complete because it is blocked on bcrypt's CS held by Thread A.
This only happens when the DLL needed by BCrypt has not yet been loaded (first BCrypt call in the process), and a new thread happens to start in the
narrow window during which Thread A holds bcrypt's CS inside LoadLibraryEx. The window is typically a few milliseconds, making this rare but
possible.
- is related to
-
SERVER-121475 Refactor hashing salt initialization for resource id
-
- Closed
-