From 7b00f39140547c6aceaf1c40c1e45df96e8e5dc2 Mon Sep 17 00:00:00 2001 From: Dmitry Kovba Date: Mon, 11 Aug 2025 09:26:31 -0700 Subject: [PATCH] Close a handle inside a lock (#257) Improves https://github.com/apple/containerization/pull/245. A potential deadlock risk was not proven. This PR moves the closing operation inside the lock to prevent leaking an unclosed handle in case of an error. --- Sources/ContainerizationOS/Socket/Socket.swift | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Sources/ContainerizationOS/Socket/Socket.swift b/Sources/ContainerizationOS/Socket/Socket.swift index 94b03ec5..d3b1708e 100644 --- a/Sources/ContainerizationOS/Socket/Socket.swift +++ b/Sources/ContainerizationOS/Socket/Socket.swift @@ -179,25 +179,24 @@ extension Socket { } public func close() throws { - let (handleToClose, sourceToCancel) = state.withLock { currentState -> (FileHandle?, DispatchSourceRead?) in + try state.withLock { currentState in guard let handle = currentState.handle else { // Already closed. - return (nil, nil) + return } + let acceptSource = currentState.acceptSource + + acceptSource?.cancel() + try handle.close() + currentState = State( socketState: currentState.socketState, handle: nil, type: currentState.type, acceptSource: nil ) - - return (handle, currentState.acceptSource) } - - // Close outside the lock to avoid a deadlock. - sourceToCancel?.cancel() - try handleToClose?.close() } public func write(data: any DataProtocol) throws -> Int {