Skip to content

Fix XPCClient ContinuationResolver deadlock#1987

Open
lakshitsoni26 wants to merge 1 commit into
apple:mainfrom
lakshitsoni26:fix-xpc-continuation-deadlock
Open

Fix XPCClient ContinuationResolver deadlock#1987
lakshitsoni26 wants to merge 1 commit into
apple:mainfrom
lakshitsoni26:fix-xpc-continuation-deadlock

Conversation

@lakshitsoni26

@lakshitsoni26 lakshitsoni26 commented Jul 22, 2026

Copy link
Copy Markdown

Fix #2007

Motivation and Context

This PR addresses a fatal concurrency issue in XPCClient.swift where a race condition between an XPC timeout and a delayed XPC reply can cause a Swift task continuation misuse crash or a permanent task group hang.

Previously, the XPCClient.send() method utilized a withThrowingTaskGroup to race a timeout task against an XPC callback. However, because Swift Task cancellation cannot cancel registered C libxpc callbacks, if the timeout elapsed first, the XPC callback could still fire later. This led to a fatal SWIFT TASK CONTINUATION MISUSE crash (resuming a continuation more than once). Furthermore, because waitForAll() was used, certain XPC hanging behaviors could cause the task group to deadlock indefinitely.

Description

This PR refactors XPCClient.send() to safely bridge the C-level XPC callback into Swift Concurrency:

  • Introduces a private ContinuationResolver actor to wrap the CheckedContinuation.
  • The actor guarantees thread-safe, atomic resolution, ensuring the continuation is resumed exactly once. If both the timeout and the XPC reply race to complete, the loser's call safely becomes a no-op instead of causing a fatal crash.
  • Replaces withThrowingTaskGroup with a single withCheckedThrowingContinuation and a detached timeoutTask. This removes the group.waitForAll() dependency, preventing the deadlock entirely while cleanly isolating the C-callback lifecycle.

Testing

  • Verified make check passes with zero formatting or header issues.
  • Verified swift test passes locally without deadlocks.
  • Tested against simulated XPC hang environments to confirm the timeout resolves instantly without crashing when the delayed reply eventually arrives.

@jglogan

jglogan commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@lakshitsoni26 Can you create an issue for this fix that provides concrete reproduction steps for the bug?

@lakshitsoni26

Copy link
Copy Markdown
Author

@lakshitsoni26 Can you create an issue for this fix that provides concrete reproduction steps for the bug?

Done! I have created issue #2007 with the concrete reproduction steps and test case for this crash: #2007

I have also updated the PR description to link directly to #2007.

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.

[Bug]: XPCClient causes fatal SWIFT TASK CONTINUATION MISUSE crash on delayed replies

2 participants