Skip to content

CheckedContinuation never resumed in NetworkTransport send/receive on actor dealloc (Swift 6.3) #214

@doozMen

Description

@doozMen

Bug

When NetworkTransport is deallocated while an async send(), sendHeartbeat(), or receiveData() operation is in-flight, the CheckedContinuation inside the NWConnection completion handler is never resumed — causing a permanent deadlock.

Root Cause

The .contentProcessed completion closures capture [weak self] but do not capture continuation directly. When self becomes nil in the completion handler, the guard let self else { return } exits without resuming the continuation.

This violates Swift's CheckedContinuation contract: a continuation must be resumed exactly once. Never resuming causes the caller to hang forever. In debug builds (Swift 6.3), this produces a runtime warning.

Affected Methods

  • NetworkTransport.send(_ message: Data).contentProcessed completion
  • NetworkTransport.sendHeartbeat().contentProcessed completion
  • NetworkTransport.receiveData()connection.receive completion (strong self capture inconsistency)

Reproduction

  1. Create a NetworkTransport connection
  2. Start a send() call
  3. Deallocate the transport before the NWConnection completion fires
  4. The caller hangs indefinitely

Environment

  • Swift 6.3 (also affects earlier versions, but Swift 6.3 strict concurrency makes it more visible)
  • Network framework (NWConnection)

Fix

Capture continuation directly in completion closures alongside [weak self], and resume with an error in the guard's else branch. See PR #213.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions