Skip to content

[SR-15697] Program crashes when calling asynchronous method multiple times on Windows #57976

Closed
@MarSe32m

Description

@MarSe32m
Previous ID SR-15697
Radar None
Original Reporter @MarSe32m
Type Bug

Attachment: Download

Environment

Windows 10.

Swift snapshot: swift-DEVELOPMENT-SNAPSHOT-2021-12-23-a

Additional Detail from JIRA
Votes 0
Component/s
Labels Bug, Concurrency, Windows
Assignee None
Priority Medium

md5: 9524581afb3bfc618b5c9a4c56b3bd35

Issue Description:

The following program crashes, after some 6000_ish_ iterations of the receive loop, in the following situations:

  • running the program with swift run and using the local (LocalAsyncStack) variable

  • running the program with swift run and using the module (AsyncStack) variable from AsyncStackModule

  • running the program with swift run and using the module (AsyncStack) variable from the AsyncStackModule

The program doesn't crash when its run with swift run -c release and using the local (LocalAsyncStack) variable.

All of the crashing cases disappear when the async is removed from the receive method, i.e. when

public mutating func receive() async -> Element?

is changed to

public mutating func receive() -> Element?

for both LocalAsyncStack and the AsyncStack from the AsyncStackModule.

When the send method of the (Local)AsyncStack is made async, then the program crashes on the first call to the send method. This crash appears on the same cases as mentioned above. This crash doesn't appear when ran with swift run -c release with LocalAsyncStack.

Target asyngbugtwo:
App.swift

import AsyncStackModule

@main
public struct App {
    public static func main() async {
        // var local = LocalAsyncStack<Int>()
        var module = AsyncStack<Int>()

        let upperBound = 100000
        for i in 0...upperBound {
            // await local.send(i)
            await module.send(i)
            if i % 10000 == 0 {
                print(i)
            }
        }

        var index = 0
        // while let value = await local.receive() {
        while let value = await module.receive() {
            precondition(index == upperBound - value)
            print("value", value)
            index += 1
        }
        print("Done:", index)
    }
}

LocalAsyncStack.swift

public struct LocalAsyncStack<Element>: @unchecked Sendable {
    var buffer = [Element]()

    public init() {}

    public mutating func send(_ value: Element) {
        buffer.append(value)
    }

    public mutating func receive() async -> Element? {
        buffer.popLast()
    }
}

Target AsyncStackModule:
AsyncStack.swift (identical to LocalAsyncStack)

public struct AsyncStack<Element>: @unchecked Sendable {
    var buffer = [Element]()

    public init() {}

    public mutating func send(_ value: Element) {
        buffer.append(value)
    }

    public mutating func receive() async -> Element? {
        buffer.popLast()
    }
}

Package.swift

// swift-tools-version: 5.5
import PackageDescription

let package = Package(
    name: "asyncbugtwo",
    targets: [
        .target(name: "AsyncStackModule"),
        .executableTarget(name: "asyncbugtwo", dependencies: ["AsyncStackModule"])
    ]
)

I can't reproduce this behavior on Linux or macOS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CodeGenWindowsPlatform: Windowsasync & awaitFeature → concurrency: asynchronous function aka the async/await patternbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.concurrencyFeature: umbrella label for concurrency language featurescrashBug: A crash, i.e., an abnormal termination of softwarerun-time crashBug → crash: Swift code crashed during executionswift 5.6

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions