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