Task Cancellation Bug?

Checking the isCancelled property on a Task doesn't seem to be reporting the correct value. This test fails 100/100 times:

    func testCancelBug() async {
        let t = Task {
            await Task.yield()
            XCTAssertTrue(Task.isCancelled)
        }
        
        t.cancel()
        XCTAssertTrue(t.isCancelled) // Fails here: XCTAssertTrue failed
    }

Is this a bug or intended behavior?

1 Like

Could be related to the issues I'm having detecting cancellation of subtasks in AsyncStream and Cancellation. Part of the issue here may be that you aren't waiting for cancellation to complete, and that the behavior of Task in that case isn't documented. isCancelled is synchronous, so I'd hope the updating of the state would be too, but there may be a race here.

I thought the same and so I tried the following with no change in behavior:

    func testCancelBug() async {
        let t = Task {
            await Task.yield()
            XCTAssertTrue(Task.isCancelled)
        }
        
        t.cancel()
        await Task.yield() // This yield doesn't help
        XCTAssertTrue(t.isCancelled) // Fails here: XCTAssertTrue failed
    }

Your expectation is correct; I reproduced the issue and this definitely seems quite off... We use an atomic change to mark the flag as cancelled so I'm a bit confused how this can happen.

Would you mind filing a bug on bugs.swift.org and I'll look into it in the meantime already?

sure thing: [SR-15309] Task isCancelled instance property not reporting value correctly ยท Issue #57631 ยท apple/swift ยท GitHub

2 Likes

This was a bug, fixed now -- details in SR report.

Thank you for reporting :pray:

2 Likes