Skip to content

Fix native wait lifetime during asynchronous fence completion - #938

Open
andrewsil1 wants to merge 2 commits into
Sergio0694:mainfrom
andrewsil1:codex/fix-async-fence-wait-lifetime
Open

andrewsil1 wants to merge 2 commits into
Sergio0694:mainfrom
andrewsil1:codex/fix-async-fence-wait-lifetime

Conversation

@andrewsil1

Copy link
Copy Markdown

Closes #936

Description

Asynchronous fence completion currently discards the native wait registration handle and frees its event and callback context without unregistering the wait. Retain the registration and explicitly cancel it before releasing those resources.

  • Register with WT_EXECUTEONLYONCE and coordinate handle publication with callback completion using an atomic handshake. Either ordering assigns cleanup to exactly one participant.
  • Use nonblocking UnregisterWaitEx from the callback, accepting ERROR_IO_PENDING there. When the callback arrives before publication, unregister and join it from the publishing thread instead.
  • Preserve native errors through source-generated, last-error-aware bindings. On setup failure, synchronously drain the submitted command list before recycling its allocator and release acquired wait resources. Unexpected unregistration failures fault the awaiter and retain resources whose native ownership is uncertain.

No public API changes.

Validation

Passed on Windows with .NET SDK 10.0.401, against upstream 40dbe40de0b1eafb570e2af43f78bcdbffdcc00a:

dotnet test tests/ComputeSharp.Tests.Internals/ComputeSharp.Tests.Internals.csproj --configuration Release --filter FullyQualifiedName~FenceWaitTests
dotnet test tests/ComputeSharp.Tests.Internals/ComputeSharp.Tests.Internals.csproj --configuration Release --no-build --no-restore

The full internal test project passed: 138 tests, zero failures or skips. The new GPU-independent test covers both publication orderings, duplicate arrival rejection, 10,000 concurrent publication races, cancellation-result classification, 2,000 native wait cycles with a handle-growth bound, and last-error capture. The native probe uses the production publication helper and a small test callback; it does not inject failures into the D3D12 completion path.

The complete repository test suite was not run. Device removal, allocation failures, and actual native unregistration failures were not injected. The change does not redefine the broader device-loss contract or attribute a GPU failure to this defect.

Additional context

RegisterWaitForSingleObject requires explicit cancellation even for one-shot waits. UnregisterWaitEx documents the callback deadlock constraint and pending-callback return behavior used here.

@andrewsil1
andrewsil1 marked this pull request as ready for review September 30, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async fence completion does not unregister native waits (3.2.0 and main)

1 participant