Description
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.