Skip to content

Commit b443d52

Browse files
committed
withAsyncTaskCleanupHandler calls its cleanup handler twice if body throws
If the body closure given to withAsyncTaskCleanupHandler throws, its cleanup handler is called twice: once in the catch block where body is called, and then again in the task group task once the Task.sleep throws due to cancellation, which swallows the error and then continues to call the handler as well. This results in the teardown sequence being invoked twice. Closes #80
1 parent 80bd50f commit b443d52

File tree

1 file changed

+11
-25
lines changed

1 file changed

+11
-25
lines changed

Sources/Subprocess/Configuration.swift

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -752,31 +752,17 @@ extension Optional where Wrapped == String {
752752
}
753753
}
754754

755-
internal func withAsyncTaskCleanupHandler<Result>(
756-
_ body: () async throws -> Result,
755+
internal func withAsyncTaskCleanupHandler<Success, Failure>(
756+
_ body: () async throws(Failure) -> Success,
757757
onCleanup handler: @Sendable @escaping () async -> Void,
758758
isolation: isolated (any Actor)? = #isolation
759-
) async rethrows -> Result {
760-
return try await withThrowingTaskGroup(
761-
of: Void.self,
762-
returning: Result.self
763-
) { group in
764-
group.addTask {
765-
// Keep this task sleep indefinitely until the parent task is cancelled.
766-
// `Task.sleep` throws `CancellationError` when the task is canceled
767-
// before the time ends. We then run the cancel handler.
768-
do { while true { try await Task.sleep(nanoseconds: 1_000_000_000) } } catch {}
769-
// Run task cancel handler
770-
await handler()
771-
}
772-
773-
do {
774-
let result = try await body()
775-
group.cancelAll()
776-
return result
777-
} catch {
778-
await handler()
779-
throw error
780-
}
781-
}
759+
) async throws(Failure) -> Success {
760+
let result: Result<Success, Failure>
761+
do {
762+
result = try await .success(body())
763+
} catch let e {
764+
result = .failure(e)
765+
}
766+
await handler()
767+
return try result.get()
782768
}

0 commit comments

Comments
 (0)