@@ -128,9 +128,16 @@ final class StandardIO: ManagedProcess.IO & Sendable {
128128 // `buf` isn't used concurrently.
129129 nonisolated ( unsafe) let buf = UnsafeMutableBufferPointer< UInt8> . allocate( capacity: Int ( getpagesize ( ) ) )
130130
131+ var didCleanup = false
132+ let cleanupRelay : ( ) -> Void = {
133+ if didCleanup { return }
134+ didCleanup = true
135+ self . cleanupRelay ( readFd: readFromFd, writeFd: writeToFd, buffer: buf, log: self . log)
136+ }
137+
131138 try ProcessSupervisor . default. poller. add ( readFromFd, mask: EPOLLIN) { mask in
132139 if mask. isHangup && !mask. readyToRead {
133- self . cleanupRelay ( readFd : readFromFd , writeFd : writeToFd , buffer : buf , log : self . log )
140+ cleanupRelay ( )
134141 return
135142 }
136143 // Loop so that in the case that someone wrote > buf.count down the pipe
@@ -146,7 +153,7 @@ final class StandardIO: ManagedProcess.IO & Sendable {
146153 let w = writeTo. write ( view)
147154 if w. wrote != r. read {
148155 self . log? . error ( " stopping relay: short write for stdio " )
149- self . cleanupRelay ( readFd : readFromFd , writeFd : writeToFd , buffer : buf , log : self . log )
156+ cleanupRelay ( )
150157 return
151158 }
152159 }
@@ -156,13 +163,13 @@ final class StandardIO: ManagedProcess.IO & Sendable {
156163 self . log? . error ( " failed with errno \( errno) while reading for fd \( readFromFd) " )
157164 fallthrough
158165 case . eof:
159- self . cleanupRelay ( readFd : readFromFd , writeFd : writeToFd , buffer : buf , log : self . log )
166+ cleanupRelay ( )
160167 self . log? . debug ( " closing relay for \( readFromFd) " )
161168 return
162169 case . again:
163170 // We read all we could, exit.
164171 if mask. isHangup {
165- self . cleanupRelay ( readFd : readFromFd , writeFd : writeToFd , buffer : buf , log : self . log )
172+ cleanupRelay ( )
166173 }
167174 return
168175 default :
0 commit comments