Skip to content

Commit 2400ae9

Browse files
committed
[Test][Concurrency] Fix reflect_task test to avoid a race condition.
This isn't a nice fix, because I can't see a good way to fix this problem robustly. The issue is that the Concurrency runtime may mutate the AsyncTask structure from a thread other than the one that is reflecting the current task, so looking through at the child tasks is inherently dangerous and may cause the test to crash at random, even though it will *often* work. To make this a lot less likely, add a .25s delay before reflecting the parent task. rdar://150478597
1 parent d7bdbcb commit 2400ae9

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

test/Concurrency/Reflection/reflect_task.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,35 @@ func testNestedCallsTask() async {
6363
// CHECK: Chunk at {{0x[0-9a-fA-F]*}} length {{[1-9[[0-9]*}} kind {{[0-9]*}}
6464
}
6565

66+
// ###HACK: Avoid a race condition by waiting a bit.
67+
//
68+
// If we reflect the current task immediately, there is a chance that the
69+
// runtime is busy manipulating the task structure (e.g. allocating using the
70+
// task allocator on a child task, or adding a child task) in parallel with
71+
// the reflection. This can cause this test to crash when the
72+
// swift-reflection-test binary asks to read from an uninitialized address.
73+
//
74+
// While we could stop the crashing by changing the pipe memory reader to
75+
// return error codes when it is unable to read memory, that would still
76+
// result in this test failing randomly. It's not obvious what the "proper"
77+
// fix for this should be; the Concurrency runtime isn't going to export
78+
// anything that would help here.
79+
func dodgeRaceCondition() async {
80+
if #available(SwiftStdlib 5.7, *) {
81+
try! await Task.sleep(for: .milliseconds(250))
82+
} else {
83+
fatalError("This test shouldn't be running against old stdlibs.")
84+
}
85+
}
86+
6687
func testOneAsyncLet() async {
6788
reflectionLog(str: "testOneAsyncLet")
6889
// CHECK: testOneAsyncLet
6990

7091
async let alet = sleepForever()
92+
93+
await dodgeRaceCondition()
94+
7195
reflect(asyncTask: _getCurrentTaskShim())
7296
// CHECK: Async task {{0x[0-9a-fA-F]*}}
7397
// CHECK: children = {
@@ -81,6 +105,9 @@ func testMultipleAsyncLet() async {
81105

82106
async let alet1 = sleepForever()
83107
async let alet2 = sleepForever()
108+
109+
await dodgeRaceCondition()
110+
84111
reflect(asyncTask: _getCurrentTaskShim())
85112
// CHECK: Async task {{0x[0-9a-fA-F]*}}
86113
// CHECK: children = {

0 commit comments

Comments
 (0)