Fix Windows startup deadlock caused by BCryptOpenAlgorithmProvider DLL load

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 9.0.0-rc0
    • Affects Version/s: None
    • Component/s: Security
    • None
    • Server Security
    • Fully Compatible
    • ALL
    • Server Security 2026-04-24
    • 200
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      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.

            Assignee:
            Chye Lin Chee
            Reporter:
            Erwin Pe
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: