@@ -222,24 +222,50 @@ public class HTTPClient {
222222 """
223223 )
224224 }
225- let errorStorage : NIOLockedValueBox < Error ? > = NIOLockedValueBox ( nil )
226- let dispatchGroup = DispatchGroup ( )
227- dispatchGroup. enter ( )
228- self . shutdown ( requiresCleanClose: requiresCleanClose, queue: DispatchQueue ( label: " async-http-client.shutdown " ) )
229- { error in
230- if let error = error {
231- errorStorage. withLockedValue { errorStorage in
232- errorStorage = error
225+
226+ final class ShutdownError : @unchecked Sendable {
227+ // @unchecked because error is protected by lock.
228+
229+ // Stores whether the shutdown has happened or not.
230+ private let lock : ConditionLock < Bool >
231+ private var error : Error ?
232+
233+ init ( ) {
234+ self . error = nil
235+ self . lock = ConditionLock ( value: false )
236+ }
237+
238+ func didShutdown( _ error: ( any Error ) ? ) {
239+ self . lock. lock ( whenValue: false )
240+ defer {
241+ self . lock. unlock ( withValue: true )
233242 }
243+ self . error = error
234244 }
235- dispatchGroup. leave ( )
236- }
237- dispatchGroup. wait ( )
238- try errorStorage. withLockedValue { errorStorage in
239- if let error = errorStorage {
240- throw error
245+
246+ func blockUntilShutdown( ) -> ( any Error ) ? {
247+ self . lock. lock ( whenValue: true )
248+ defer {
249+ self . lock. unlock ( withValue: true )
250+ }
251+ return self . error
241252 }
242253 }
254+
255+ let shutdownError = ShutdownError ( )
256+
257+ self . shutdown (
258+ requiresCleanClose: requiresCleanClose,
259+ queue: DispatchQueue ( label: " async-http-client.shutdown " )
260+ ) { error in
261+ shutdownError. didShutdown ( error)
262+ }
263+
264+ let error = shutdownError. blockUntilShutdown ( )
265+
266+ if let error = error {
267+ throw error
268+ }
243269 }
244270
245271 /// Shuts down the client and event loop gracefully.
0 commit comments