Skip to content

[tests] Await async cancellation in SecProtocolMetadataTest to avoid a hang - #25682

Merged
dalexsoto merged 1 commit into
mainfrom
dev/alex/3921131077
Jun 15, 2026
Merged

dalexsoto merged 1 commit into
mainfrom
dev/alex/3921131077

Conversation

@dalexsoto

Copy link
Copy Markdown
Member

SecProtocolMetadataTest.TlsDefaults starts an NWConnection on a DispatchQueue created with a 'using' block and registers a state-change handler that disposes the connection when it reaches the Cancelled/Failed state. The handler runs on that queue, but the test disposed the queue (leaving the 'using' scope) without waiting for the asynchronous cancellation to complete, and skipped the trailing Cancel () entirely whenever Assert.Fail / IgnoreInCI threw. The cancellation callback could therefore still be pending - and run on a disposed queue - long after the test finished, contributing to a process-wide hang on the macOS test run (observed as a ~20 minute timeout / "Test run crashed").

Wrap the body in try/finally and signal a ManualResetEvent from the Cancelled/Failed branch of the handler. The finally cancels the connection and waits (bounded to 10s) for that event before the queue is disposed, on every path (success, the Assert.Fail, an assertion failure inside the inner 'using', and the IgnoreInCI case). Cancel () is guarded against ObjectDisposedException so that, if the connection already failed on its own and the handler disposed it, the original test failure is preserved instead of being masked.

…a hang

SecProtocolMetadataTest.TlsDefaults starts an NWConnection on a DispatchQueue
created with a 'using' block and registers a state-change handler that disposes
the connection when it reaches the Cancelled/Failed state. The handler runs on
that queue, but the test disposed the queue (leaving the 'using' scope) without
waiting for the asynchronous cancellation to complete, and skipped the trailing
Cancel () entirely whenever Assert.Fail / IgnoreInCI threw. The cancellation
callback could therefore still be pending - and run on a disposed queue - long
after the test finished, contributing to a process-wide hang on the macOS test
run (observed as a ~20 minute timeout / "Test run crashed").

Wrap the body in try/finally and signal a ManualResetEvent from the
Cancelled/Failed branch of the handler. The finally cancels the connection and
waits (bounded to 10s) for that event before the queue is disposed, on every
path (success, the Assert.Fail, an assertion failure inside the inner 'using',
and the IgnoreInCI case). Cancel () is guarded against ObjectDisposedException
so that, if the connection already failed on its own and the handler disposed
it, the original test failure is preserved instead of being masked.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves reliability of SecProtocolMetadataTest.TlsDefaults by ensuring NWConnection cancellation completes before the DispatchQueue used for callbacks is disposed, preventing post-test callbacks from running on a disposed queue (and avoiding potential hangs in macOS test runs).

Changes:

  • Add a ManualResetEvent (done) that is signaled when the connection reaches a terminal state (Cancelled/Failed).
  • Wrap test execution in try/finally to always cancel the connection and wait (bounded) for asynchronous cancellation before leaving the queue’s using scope.
  • Guard connection.Cancel() against ObjectDisposedException to preserve the original test failure/ignore outcome.

// If we're in CI, and didn't get _any_ callbacks, then ignore the failure, since it's likely a network hiccup.
if (!anyStateChange.WaitOne (0))
TestRuntime.IgnoreInCI ("Transient network failure - ignore in CI");
Assert.Fail ("Connection is ready");
@rolfbjarne

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 3 pipeline(s).

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

βœ… [PR Build #d519280] Build passed (Detect API changes) βœ…

Pipeline on Agent
Hash: d519280a1c00196eb6032bc0f3b05df1795609fd [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

βœ… [PR Build #d519280] Build passed (Build packages) βœ…

Pipeline on Agent
Hash: d519280a1c00196eb6032bc0f3b05df1795609fd [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

βœ… API diff for current PR / commit

NET (empty diffs)

βœ… API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: d519280a1c00196eb6032bc0f3b05df1795609fd [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

βœ… [PR Build #d519280] Build passed (Build macOS tests) βœ…

Pipeline on Agent
Hash: d519280a1c00196eb6032bc0f3b05df1795609fd [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

πŸ”₯ [CI Build #d519280] Test results πŸ”₯

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 1 tests failed, 192 tests passed.

Failures

❌ introspection tests [attempt 3]

1 tests failed, 5 tests passed.

Failed tests

  • introspection/macOS/Debug: Failed (Test run failed.
    Tests run: 34 Passed: 33 Inconclusive: 0 Failed: 1 Ignored: 0)

Html Report (VSDrops) Download

Successes

βœ… cecil: All 1 tests passed. Html Report (VSDrops) Download
βœ… dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
βœ… dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
βœ… dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
βœ… dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
βœ… dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
βœ… framework: All 2 tests passed. Html Report (VSDrops) Download
βœ… fsharp: All 4 tests passed. [attempt 2] Html Report (VSDrops) Download
βœ… generator: All 5 tests passed. Html Report (VSDrops) Download
βœ… interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
βœ… linker (iOS): All 11 tests passed. Html Report (VSDrops) Download
βœ… linker (MacCatalyst): All 11 tests passed. Html Report (VSDrops) Download
βœ… linker (macOS): All 11 tests passed. Html Report (VSDrops) Download
βœ… linker (tvOS): All 11 tests passed. Html Report (VSDrops) Download
βœ… monotouch (iOS): All 20 tests passed. Html Report (VSDrops) Download
βœ… monotouch (MacCatalyst): All 23 tests passed. [attempt 2] Html Report (VSDrops) Download
βœ… monotouch (macOS): All 23 tests passed. Html Report (VSDrops) Download
βœ… monotouch (tvOS): All 20 tests passed. Html Report (VSDrops) Download
βœ… msbuild: All 2 tests passed. Html Report (VSDrops) Download
βœ… sharpie: All 1 tests passed. Html Report (VSDrops) Download
βœ… windows: All 3 tests passed. Html Report (VSDrops) Download
βœ… xcframework: All 4 tests passed. Html Report (VSDrops) Download
βœ… xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

βœ… Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
βœ… Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
βœ… Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
βœ… Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
βœ… Tests on macOS Tahoe (26): All 5 tests passed. [attempt 2] Html Report (VSDrops) Download

Linux Build Verification

βœ… Linux build succeeded

Pipeline on Agent
Hash: d519280a1c00196eb6032bc0f3b05df1795609fd [PR build]

@dalexsoto

Copy link
Copy Markdown
Member Author

unrelated test failure
image

@dalexsoto
dalexsoto merged commit 49f9fa0 into main Jun 15, 2026
54 of 56 checks passed
@dalexsoto
dalexsoto deleted the dev/alex/3921131077 branch June 15, 2026 21:43
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.

4 participants