@@ -74,28 +74,26 @@ 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
- 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
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)))
99
97
if err != 0
100
98
ccall (:jl_forceclose_uv , Cvoid, (Ptr{Cvoid},), handle) # will call free on handle eventually
101
99
throw (_UVError (" could not spawn " * repr (cmd), err))
@@ -211,10 +209,10 @@ function setup_stdio(stdio::PipeEndpoint, child_readable::Bool)
211
209
rd, wr = link_pipe (! child_readable, child_readable)
212
210
try
213
211
open_pipe! (stdio, child_readable ? wr : rd)
214
- catch
212
+ catch ex
215
213
close_pipe_sync (rd)
216
214
close_pipe_sync (wr)
217
- rethrow ()
215
+ rethrow (ex )
218
216
end
219
217
child = child_readable ? rd : wr
220
218
return (child, true )
@@ -253,18 +251,18 @@ function setup_stdio(stdio::FileRedirect, child_readable::Bool)
253
251
return (io, true )
254
252
end
255
253
256
- # incrementally move data between an arbitrary IO and a system Pipe
254
+ # incrementally move data between an IOBuffer and a system Pipe
257
255
# TODO : probably more efficient (when valid) to use `stdio` directly as the
258
256
# PipeEndpoint buffer field in some cases
259
- function setup_stdio (stdio:: IO , child_readable:: Bool )
257
+ function setup_stdio (stdio:: Union{IOBuffer, BufferStream} , child_readable:: Bool )
260
258
parent = PipeEndpoint ()
261
259
rd, wr = link_pipe (! child_readable, child_readable)
262
260
try
263
261
open_pipe! (parent, child_readable ? wr : rd)
264
- catch
262
+ catch ex
265
263
close_pipe_sync (rd)
266
264
close_pipe_sync (wr)
267
- rethrow ()
265
+ rethrow (ex )
268
266
end
269
267
child = child_readable ? rd : wr
270
268
try
@@ -273,18 +271,24 @@ function setup_stdio(stdio::IO, child_readable::Bool)
273
271
@async try
274
272
write (in, out)
275
273
catch ex
276
- @warn " Process I/O error" exception= (ex, catch_backtrace ())
274
+ @warn " Process error" exception= (ex, catch_backtrace ())
277
275
finally
278
276
close (parent)
279
277
end
280
278
end
281
- catch
279
+ catch ex
282
280
close_pipe_sync (child)
283
- rethrow ()
281
+ rethrow (ex )
284
282
end
285
283
return (child, true )
286
284
end
287
285
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
+
288
292
close_stdio (stdio:: OS_HANDLE ) = close_pipe_sync (stdio)
289
293
close_stdio (stdio) = close (stdio)
290
294
0 commit comments