@@ -176,9 +176,14 @@ package func withTimeout<T: Sendable>(
176
176
_ duration: Duration ,
177
177
_ body: @escaping @Sendable ( ) async throws -> T
178
178
) async throws -> T {
179
+ // Get the priority with which to launch the body task here so that we can pass the same priority as the initial
180
+ // priority to `withTaskPriorityChangedHandler`. Otherwise, we can get into a race condition where bodyTask gets
181
+ // launched with a low priority, then the priority gets elevated before we call with `withTaskPriorityChangedHandler`,
182
+ // we thus don't receive a `taskPriorityChanged` and hence never increase the priority of `bodyTask`.
183
+ let priority = Task . currentPriority
179
184
var mutableTasks : [ Task < Void , Error > ] = [ ]
180
185
let stream = AsyncThrowingStream < T , Error > { continuation in
181
- let bodyTask = Task < Void , Error > {
186
+ let bodyTask = Task < Void , Error > ( priority : priority ) {
182
187
do {
183
188
let result = try await body ( )
184
189
continuation. yield ( result)
@@ -187,7 +192,7 @@ package func withTimeout<T: Sendable>(
187
192
}
188
193
}
189
194
190
- let timeoutTask = Task {
195
+ let timeoutTask = Task ( priority : priority ) {
191
196
try await Task . sleep ( for: duration)
192
197
continuation. yield ( with: . failure( TimeoutError ( ) ) )
193
198
bodyTask. cancel ( )
@@ -197,7 +202,7 @@ package func withTimeout<T: Sendable>(
197
202
198
203
let tasks = mutableTasks
199
204
200
- return try await withTaskPriorityChangedHandler {
205
+ return try await withTaskPriorityChangedHandler ( initialPriority : priority ) {
201
206
for try await value in stream {
202
207
return value
203
208
}
0 commit comments