[WebGPU] Fix OrtReleaseEnv self-deadlock after failed adapter request on Linux#29591
Merged
Conversation
Two root causes addressed: 1. (Primary) ORT_ENFORCE inside Dawn WaitAny callbacks threw C++ exceptions, which propagated through Dawn code that doesn't release its internal mutexes on exception. This left an EventManager mutex locked. When OrtEnv::~OrtEnv() later called Cleanup() -> wgpuInstanceRelease -> EventManager::ShutDown(), it tried to acquire that same mutex -> self-deadlock. Fix: capture adapter/device request status in a local struct and check it (throwing if needed) AFTER WaitAny returns, so no exception ever propagates through Dawn's internal stack. 2. (Secondary) When Initialize() threw, the WebGpuContext remained in the contexts_ map with ref_count=1 and no owner. Cleanup() would later destroy it, triggering the (now-absent) deadlock path, and also leaking the entry permanently. Fix: wrap Initialize() in a try/catch in CreateContext(); on failure decrement the ref_count and erase the entry if it reaches zero. Fixes #29553
Copilot
AI
changed the title
[WIP] Fix OrtReleaseEnv deadlock after failed Vulkan adapter request
[WebGPU] Fix OrtReleaseEnv self-deadlock after failed adapter request on Linux
Jul 7, 2026
skottmckay
reviewed
Jul 7, 2026
edgchen1
reviewed
Jul 7, 2026
… build compatibility
edgchen1
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Linux with the WebGPU EP, if
SessionOptionsAppendExecutionProvideris called when no Vulkan adapter is available, a subsequentOrtReleaseEnvon the same thread hangs forever in a futex wait.Root causes
1. C++ exceptions thrown inside Dawn
WaitAnycallbacks (primary)ORT_ENFORCEwas called directly inside theRequestAdapter/RequestDevicecallback lambdas. Dawn'sWaitAnydoes not release its internalEventManagermutex on exception, so throwing through it leaves that mutex permanently locked. The deadlock fires later whenCleanup()callswgpuInstanceRelease→EventManager::ShutDown()→ tries to re-acquire the same mutex on the same thread.2. Zombie
WebGpuContextleft in the factory map (secondary)When
Initialize()threw, theWebGpuContextentry remained incontexts_withref_count=1and no owner — a resource leak that would also re-trigger the deadlock path atCleanup().Changes (
webgpu_context.cc)Adapter callback: replace the throwing lambda with a non-throwing one that writes into a local
RequestAdapterResultstruct;ORT_ENFORCEis moved to afterWaitAnyreturns:Device callback: same pattern applied to
RequestDevice.CreateContextcleanup: wrapInitialize()in atry/catch; on failure decrementref_countand erase the entry fromcontexts_if it reaches zero.Motivation and Context
Fixes the hang reported when registering the WebGPU EP with no usable Vulkan adapter and then calling
OrtReleaseEnv. The process would park on a futex with__ownerset to its own TID — a non-recursive mutex locked twice on the same thread — and never exit.