Skip to content

withUnsafeContinuation can break actor isolation #61485

Closed as not planned
Closed as not planned
@groue

Description

@groue

Describe the bug

Hello, withUnsafeContinuation is able to break actor invariants that should be protected by actor isolation.

Steps To Reproduce

The following test instantiates one actor, and performs as many increments as decrements of an isolated count property. It tests that the final value is the initial one: zero.

func test_that_UnsafeContinuation_can_not_break_actor_isolation() async {
    actor MyActor {
        var count = 0
        
        func zero() async {
            count += 1
            await withUnsafeContinuation { continuation in
                count -= 1
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    continuation.resume()
                }
            }
        }
    }
    
    do {
        let actor = MyActor()
        await withTaskGroup(of: Void.self) { group in
            for _ in 0..<1_000 {
                group.addTask {
                    await actor.zero()
                }
            }
        }
        
        let count = await actor.count
        // Failure varies:
        // XCTAssertEqual failed: ("1") is not equal to ("0")
        // XCTAssertEqual failed: ("4") is not equal to ("0")
        // XCTAssertEqual failed: ("7") is not equal to ("0")
        XCTAssertEqual(count, 0)
    }
}

Expected behavior

The above test passes without failure.

Environment (please fill out the following information)

  • OS: macOS 12.5.1 (21G83)
  • Xcode Version/Tag/Branch: Version 14.0.1 (14A400)

Additional context

I stumbled upon this buggy (right?) behavior while exploring the difficulties using unsafe continuations in this discussion about the implementation of a counting semaphore for swift concurrency: groue/Semaphore#2 (reply in thread).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.concurrencyFeature: umbrella label for concurrency language featuresruntimeThe Swift Runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions