@@ -74,26 +74,28 @@ const SpawnIOs = Vector{Any} # convenience name for readability
74
74
# handle marshalling of `Cmd` arguments from Julia to C
75
75
@noinline function _spawn_primitive (file, cmd:: Cmd , stdio:: SpawnIOs )
76
76
loop = eventloop ()
77
- iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout
78
- let h = rawhandle (io)
79
- h === C_NULL ? (0x00 , UInt (0 )) :
80
- h isa OS_HANDLE ? (0x02 , UInt (cconvert (@static (Sys. iswindows () ? Ptr{Cvoid} : Cint), h))) :
81
- h isa Ptr{Cvoid} ? (0x04 , UInt (h)) :
82
- error (" invalid spawn handle $h from $io " )
83
- end
84
- for io in stdio]
85
- handle = Libc. malloc (_sizeof_uv_process)
86
- disassociate_julia_struct (handle) # ensure that data field is set to C_NULL
87
- err = ccall (:jl_spawn , Int32,
88
- (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid},
89
- Ptr{Tuple{Cint, UInt}}, Int,
90
- UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}),
91
- file, cmd. exec, loop, handle,
92
- iohandles, length (iohandles),
93
- cmd. flags,
94
- cmd. env === nothing ? C_NULL : cmd. env,
95
- isempty (cmd. dir) ? C_NULL : cmd. dir,
96
- @cfunction (uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32)))
77
+ GC. @preserve stdio begin
78
+ iohandles = Tuple{Cint, UInt}[ # assuming little-endian layout
79
+ let h = rawhandle (io)
80
+ h === C_NULL ? (0x00 , UInt (0 )) :
81
+ h isa OS_HANDLE ? (0x02 , UInt (cconvert (@static (Sys. iswindows () ? Ptr{Cvoid} : Cint), h))) :
82
+ h isa Ptr{Cvoid} ? (0x04 , UInt (h)) :
83
+ error (" invalid spawn handle $h from $io " )
84
+ end
85
+ for io in stdio]
86
+ handle = Libc. malloc (_sizeof_uv_process)
87
+ disassociate_julia_struct (handle) # ensure that data field is set to C_NULL
88
+ err = ccall (:jl_spawn , Int32,
89
+ (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid},
90
+ Ptr{Tuple{Cint, UInt}}, Int,
91
+ UInt32, Ptr{Cstring}, Cstring, Ptr{Cvoid}),
92
+ file, cmd. exec, loop, handle,
93
+ iohandles, length (iohandles),
94
+ cmd. flags,
95
+ cmd. env === nothing ? C_NULL : cmd. env,
96
+ isempty (cmd. dir) ? C_NULL : cmd. dir,
97
+ @cfunction (uv_return_spawn, Cvoid, (Ptr{Cvoid}, Int64, Int32)))
98
+ end
97
99
if err != 0
98
100
ccall (:jl_forceclose_uv , Cvoid, (Ptr{Cvoid},), handle) # will call free on handle eventually
99
101
throw (_UVError (" could not spawn " * repr (cmd), err))
@@ -209,10 +211,10 @@ function setup_stdio(stdio::PipeEndpoint, child_readable::Bool)
209
211
rd, wr = link_pipe (! child_readable, child_readable)
210
212
try
211
213
open_pipe! (stdio, child_readable ? wr : rd)
212
- catch ex
214
+ catch
213
215
close_pipe_sync (rd)
214
216
close_pipe_sync (wr)
215
- rethrow (ex )
217
+ rethrow ()
216
218
end
217
219
child = child_readable ? rd : wr
218
220
return (child, true )
@@ -251,18 +253,18 @@ function setup_stdio(stdio::FileRedirect, child_readable::Bool)
251
253
return (io, true )
252
254
end
253
255
254
- # incrementally move data between an IOBuffer and a system Pipe
256
+ # incrementally move data between an arbitrary IO and a system Pipe
255
257
# TODO : probably more efficient (when valid) to use `stdio` directly as the
256
258
# PipeEndpoint buffer field in some cases
257
- function setup_stdio (stdio:: Union{IOBuffer, BufferStream} , child_readable:: Bool )
259
+ function setup_stdio (stdio:: IO , child_readable:: Bool )
258
260
parent = PipeEndpoint ()
259
261
rd, wr = link_pipe (! child_readable, child_readable)
260
262
try
261
263
open_pipe! (parent, child_readable ? wr : rd)
262
- catch ex
264
+ catch
263
265
close_pipe_sync (rd)
264
266
close_pipe_sync (wr)
265
- rethrow (ex )
267
+ rethrow ()
266
268
end
267
269
child = child_readable ? rd : wr
268
270
try
@@ -271,24 +273,18 @@ function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool)
271
273
@async try
272
274
write (in, out)
273
275
catch ex
274
- @warn " Process error" exception= (ex, catch_backtrace ())
276
+ @warn " Process I/O error" exception= (ex, catch_backtrace ())
275
277
finally
276
278
close (parent)
277
279
end
278
280
end
279
- catch ex
281
+ catch
280
282
close_pipe_sync (child)
281
- rethrow (ex )
283
+ rethrow ()
282
284
end
283
285
return (child, true )
284
286
end
285
287
286
- function setup_stdio (io, child_readable:: Bool )
287
- # if there is no specialization,
288
- # assume that rawhandle is defined for it
289
- return (io, false )
290
- end
291
-
292
288
close_stdio (stdio:: OS_HANDLE ) = close_pipe_sync (stdio)
293
289
close_stdio (stdio) = close (stdio)
294
290
0 commit comments