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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions