@@ -48,19 +48,40 @@ extension Configuration {
48
48
outputPipe: consuming CreatedPipe ,
49
49
errorPipe: consuming CreatedPipe
50
50
) throws -> SpawnResult {
51
+ var inputPipeBox : CreatedPipe ? = consume inputPipe
52
+ var outputPipeBox : CreatedPipe ? = consume outputPipe
53
+ var errorPipeBox : CreatedPipe ? = consume errorPipe
54
+
55
+ var _inputPipe = inputPipeBox. take ( ) !
56
+ var _outputPipe = outputPipeBox. take ( ) !
57
+ var _errorPipe = errorPipeBox. take ( ) !
58
+
59
+ let inputReadFileDescriptor : TrackedFileDescriptor ? = _inputPipe. readFileDescriptor ( )
60
+ let inputWriteFileDescriptor : TrackedFileDescriptor ? = _inputPipe. writeFileDescriptor ( )
61
+ let outputReadFileDescriptor : TrackedFileDescriptor ? = _outputPipe. readFileDescriptor ( )
62
+ let outputWriteFileDescriptor : TrackedFileDescriptor ? = _outputPipe. writeFileDescriptor ( )
63
+ let errorReadFileDescriptor : TrackedFileDescriptor ? = _errorPipe. readFileDescriptor ( )
64
+ let errorWriteFileDescriptor : TrackedFileDescriptor ? = _errorPipe. writeFileDescriptor ( )
65
+
51
66
let (
52
67
applicationName,
53
68
commandAndArgs,
54
69
environment,
55
70
intendedWorkingDir
56
- ) = try self . preSpawn ( )
57
-
58
- var inputReadFileDescriptor : TrackedFileDescriptor ? = inputPipe. readFileDescriptor ( )
59
- var inputWriteFileDescriptor : TrackedFileDescriptor ? = inputPipe. writeFileDescriptor ( )
60
- var outputReadFileDescriptor : TrackedFileDescriptor ? = outputPipe. readFileDescriptor ( )
61
- var outputWriteFileDescriptor : TrackedFileDescriptor ? = outputPipe. writeFileDescriptor ( )
62
- var errorReadFileDescriptor : TrackedFileDescriptor ? = errorPipe. readFileDescriptor ( )
63
- var errorWriteFileDescriptor : TrackedFileDescriptor ? = errorPipe. writeFileDescriptor ( )
71
+ ) : ( String ? , String , String , String ? )
72
+ do {
73
+ ( applicationName, commandAndArgs, environment, intendedWorkingDir) = try self . preSpawn ( )
74
+ } catch {
75
+ try self . safelyCloseMultiple (
76
+ inputRead: inputReadFileDescriptor,
77
+ inputWrite: inputWriteFileDescriptor,
78
+ outputRead: outputReadFileDescriptor,
79
+ outputWrite: outputWriteFileDescriptor,
80
+ errorRead: errorReadFileDescriptor,
81
+ errorWrite: errorWriteFileDescriptor
82
+ )
83
+ throw error
84
+ }
64
85
65
86
var startupInfo = try self . generateStartupInfo (
66
87
withInputRead: inputReadFileDescriptor,
@@ -77,15 +98,15 @@ extension Configuration {
77
98
try configurator ( & createProcessFlags, & startupInfo)
78
99
}
79
100
// Spawn!
80
- try applicationName. withOptionalNTPathRepresentation { applicationNameW in
101
+ let created = try applicationName. withOptionalNTPathRepresentation { applicationNameW in
81
102
try commandAndArgs. withCString (
82
103
encodedAs: UTF16 . self
83
104
) { commandAndArgsW in
84
105
try environment. withCString (
85
106
encodedAs: UTF16 . self
86
107
) { environmentW in
87
108
try intendedWorkingDir. withOptionalNTPathRepresentation { intendedWorkingDirW in
88
- let created = CreateProcessW (
109
+ CreateProcessW (
89
110
applicationNameW,
90
111
UnsafeMutablePointer < WCHAR > ( mutating: commandAndArgsW) ,
91
112
nil , // lpProcessAttributes
@@ -97,26 +118,27 @@ extension Configuration {
97
118
& startupInfo,
98
119
& processInfo
99
120
)
100
- guard created else {
101
- let windowsError = GetLastError ( )
102
- try self . safelyCloseMultiple (
103
- inputRead: inputReadFileDescriptor. take ( ) ,
104
- inputWrite: inputWriteFileDescriptor. take ( ) ,
105
- outputRead: outputReadFileDescriptor. take ( ) ,
106
- outputWrite: outputWriteFileDescriptor. take ( ) ,
107
- errorRead: errorReadFileDescriptor. take ( ) ,
108
- errorWrite: errorWriteFileDescriptor. take ( )
109
- )
110
- throw SubprocessError (
111
- code: . init( . spawnFailed) ,
112
- underlyingError: . init( rawValue: windowsError)
113
- )
114
- }
115
121
}
116
122
}
117
123
}
118
124
}
119
125
126
+ guard created else {
127
+ let windowsError = GetLastError ( )
128
+ try self . safelyCloseMultiple (
129
+ inputRead: inputReadFileDescriptor,
130
+ inputWrite: inputWriteFileDescriptor,
131
+ outputRead: outputReadFileDescriptor,
132
+ outputWrite: outputWriteFileDescriptor,
133
+ errorRead: errorReadFileDescriptor,
134
+ errorWrite: errorWriteFileDescriptor
135
+ )
136
+ throw SubprocessError (
137
+ code: . init( . spawnFailed) ,
138
+ underlyingError: . init( rawValue: windowsError)
139
+ )
140
+ }
141
+
120
142
let pid = ProcessIdentifier (
121
143
value: processInfo. dwProcessId
122
144
)
@@ -157,19 +179,40 @@ extension Configuration {
157
179
errorPipe: consuming CreatedPipe ,
158
180
userCredentials: PlatformOptions . UserCredentials
159
181
) throws -> SpawnResult {
182
+ var inputPipeBox : CreatedPipe ? = consume inputPipe
183
+ var outputPipeBox : CreatedPipe ? = consume outputPipe
184
+ var errorPipeBox : CreatedPipe ? = consume errorPipe
185
+
186
+ var _inputPipe = inputPipeBox. take ( ) !
187
+ var _outputPipe = outputPipeBox. take ( ) !
188
+ var _errorPipe = errorPipeBox. take ( ) !
189
+
190
+ let inputReadFileDescriptor : TrackedFileDescriptor ? = _inputPipe. readFileDescriptor ( )
191
+ let inputWriteFileDescriptor : TrackedFileDescriptor ? = _inputPipe. writeFileDescriptor ( )
192
+ let outputReadFileDescriptor : TrackedFileDescriptor ? = _outputPipe. readFileDescriptor ( )
193
+ let outputWriteFileDescriptor : TrackedFileDescriptor ? = _outputPipe. writeFileDescriptor ( )
194
+ let errorReadFileDescriptor : TrackedFileDescriptor ? = _errorPipe. readFileDescriptor ( )
195
+ let errorWriteFileDescriptor : TrackedFileDescriptor ? = _errorPipe. writeFileDescriptor ( )
196
+
160
197
let (
161
198
applicationName,
162
199
commandAndArgs,
163
200
environment,
164
201
intendedWorkingDir
165
- ) = try self . preSpawn ( )
166
-
167
- var inputReadFileDescriptor : TrackedFileDescriptor ? = inputPipe. readFileDescriptor ( )
168
- var inputWriteFileDescriptor : TrackedFileDescriptor ? = inputPipe. writeFileDescriptor ( )
169
- var outputReadFileDescriptor : TrackedFileDescriptor ? = outputPipe. readFileDescriptor ( )
170
- var outputWriteFileDescriptor : TrackedFileDescriptor ? = outputPipe. writeFileDescriptor ( )
171
- var errorReadFileDescriptor : TrackedFileDescriptor ? = errorPipe. readFileDescriptor ( )
172
- var errorWriteFileDescriptor : TrackedFileDescriptor ? = errorPipe. writeFileDescriptor ( )
202
+ ) : ( String ? , String , String , String ? )
203
+ do {
204
+ ( applicationName, commandAndArgs, environment, intendedWorkingDir) = try self . preSpawn ( )
205
+ } catch {
206
+ try self . safelyCloseMultiple (
207
+ inputRead: inputReadFileDescriptor,
208
+ inputWrite: inputWriteFileDescriptor,
209
+ outputRead: outputReadFileDescriptor,
210
+ outputWrite: outputWriteFileDescriptor,
211
+ errorRead: errorReadFileDescriptor,
212
+ errorWrite: errorWriteFileDescriptor
213
+ )
214
+ throw error
215
+ }
173
216
174
217
var startupInfo = try self . generateStartupInfo (
175
218
withInputRead: inputReadFileDescriptor,
@@ -186,7 +229,7 @@ extension Configuration {
186
229
try configurator ( & createProcessFlags, & startupInfo)
187
230
}
188
231
// Spawn (featuring pyramid!)
189
- try userCredentials. username. withCString (
232
+ let created = try userCredentials. username. withCString (
190
233
encodedAs: UTF16 . self
191
234
) { usernameW in
192
235
try userCredentials. password. withCString (
@@ -203,7 +246,7 @@ extension Configuration {
203
246
encodedAs: UTF16 . self
204
247
) { environmentW in
205
248
try intendedWorkingDir. withOptionalNTPathRepresentation { intendedWorkingDirW in
206
- let created = CreateProcessWithLogonW (
249
+ CreateProcessWithLogonW (
207
250
usernameW,
208
251
domainW,
209
252
passwordW,
@@ -216,21 +259,6 @@ extension Configuration {
216
259
& startupInfo,
217
260
& processInfo
218
261
)
219
- guard created else {
220
- let windowsError = GetLastError ( )
221
- try self . safelyCloseMultiple (
222
- inputRead: inputReadFileDescriptor. take ( ) ,
223
- inputWrite: inputWriteFileDescriptor. take ( ) ,
224
- outputRead: outputReadFileDescriptor. take ( ) ,
225
- outputWrite: outputWriteFileDescriptor. take ( ) ,
226
- errorRead: errorReadFileDescriptor. take ( ) ,
227
- errorWrite: errorWriteFileDescriptor. take ( )
228
- )
229
- throw SubprocessError (
230
- code: . init( . spawnFailed) ,
231
- underlyingError: . init( rawValue: windowsError)
232
- )
233
- }
234
262
}
235
263
}
236
264
}
@@ -239,6 +267,22 @@ extension Configuration {
239
267
}
240
268
}
241
269
270
+ guard created else {
271
+ let windowsError = GetLastError ( )
272
+ try self . safelyCloseMultiple (
273
+ inputRead: inputReadFileDescriptor,
274
+ inputWrite: inputWriteFileDescriptor,
275
+ outputRead: outputReadFileDescriptor,
276
+ outputWrite: outputWriteFileDescriptor,
277
+ errorRead: errorReadFileDescriptor,
278
+ errorWrite: errorWriteFileDescriptor
279
+ )
280
+ throw SubprocessError (
281
+ code: . init( . spawnFailed) ,
282
+ underlyingError: . init( rawValue: windowsError)
283
+ )
284
+ }
285
+
242
286
let pid = ProcessIdentifier (
243
287
value: processInfo. dwProcessId
244
288
)
@@ -1038,10 +1082,9 @@ extension FileDescriptor {
1038
1082
1039
1083
extension TrackedFileDescriptor {
1040
1084
internal consuming func createPlatformDiskIO( ) -> TrackedPlatformDiskIO {
1041
- return . init(
1042
- self . fileDescriptor,
1043
- closeWhenDone: self . closeWhenDone
1044
- )
1085
+ // TrackedPlatformDiskIO is a typealias of TrackedFileDescriptor on Windows (they're the same type)
1086
+ // Just return the same object so we don't create a copy and try to double-close the fd.
1087
+ return self
1045
1088
}
1046
1089
1047
1090
internal func readUntilEOF(
0 commit comments