Skip to content

Commit 8ee0ec5

Browse files
committed
[Concurrency] Make deinit check test not racy
The test is checking that the task executor deinit runs after task completes. This deinit is caused on a different thread, and thus is racing with the main() completing. This is racy because as main() exits, we just exit the process and may not see the deinit get printed, making the test look like the deinit "didnt trigger" but it did, just was "late to the party" resolves rdar://130528198
1 parent bd7157a commit 8ee0ec5

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

test/Concurrency/Runtime/async_task_executor_unstructured_task_ownership.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,28 @@ import Dispatch
1111
import StdlibUnittest
1212
import _Concurrency
1313

14+
// For sleep
15+
#if canImport(Darwin)
16+
import Darwin
17+
#elseif canImport(Glibc)
18+
import Glibc
19+
#elseif canImport(Android)
20+
import Android
21+
#endif
22+
1423
final class NaiveQueueExecutor: TaskExecutor {
1524
let queue: DispatchQueue
25+
let sem: DispatchSemaphore
1626

17-
init(_ queue: DispatchQueue) {
27+
init(_ sem: DispatchSemaphore, _ queue: DispatchQueue) {
1828
print("init \(Self.self)")
29+
self.sem = sem
1930
self.queue = queue
2031
}
2132

2233
deinit {
2334
print("deinit \(Self.self)")
35+
sem.signal()
2436
}
2537

2638
public func enqueue(_ _job: consuming ExecutorJob) {
@@ -39,15 +51,16 @@ final class NaiveQueueExecutor: TaskExecutor {
3951
}
4052

4153
nonisolated func nonisolatedFunc(expectedQueue queue: DispatchQueue) async {
42-
// dispatchPrecondition(condition: .onQueue(queue))
54+
dispatchPrecondition(condition: .onQueue(queue))
4355
print("Invoked: \(#function)")
4456
}
4557

4658
@main struct Main {
4759

4860
static func main() async {
4961
let queue = DispatchQueue(label: "example-queue")
50-
var executor: NaiveQueueExecutor? = NaiveQueueExecutor(queue)
62+
let deinitSem = DispatchSemaphore(value: 0)
63+
var executor: NaiveQueueExecutor? = NaiveQueueExecutor(deinitSem, queue)
5164

5265
// Task retains the executor, so it should never deinit before the task completes
5366
// CHECK: init NaiveQueueExecutor
@@ -75,6 +88,8 @@ nonisolated func nonisolatedFunc(expectedQueue queue: DispatchQueue) async {
7588
// CHECK: Task done
7689
// CHECK-NEXT: deinit NaiveQueueExecutor
7790

91+
deinitSem.wait()
92+
7893
print("Done")
7994
// CHECK: Done
8095
}

0 commit comments

Comments
 (0)