Skip to content

Commit 7135813

Browse files
authored
Revert "Revert "change setup_stdio default method to support any IO (#40780)" (#40971)"
This reverts commit 7edd190.
1 parent 7edd190 commit 7135813

File tree

5 files changed

+43
-36
lines changed

5 files changed

+43
-36
lines changed

base/cmd.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ rawhandle(x::OS_HANDLE) = x
165165
if OS_HANDLE !== RawFD
166166
rawhandle(x::RawFD) = Libc._get_osfhandle(x)
167167
end
168+
setup_stdio(stdio::Union{DevNull,OS_HANDLE,RawFD}, ::Bool) = (stdio, false)
168169

169170
const Redirectable = Union{IO, FileRedirect, RawFD, OS_HANDLE}
170171
const StdIOSet = NTuple{3, Redirectable}

base/filesystem.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import .Base:
4242
IOError, _UVError, _sizeof_uv_fs, check_open, close, eof, eventloop, fd, isopen,
4343
bytesavailable, position, read, read!, readavailable, seek, seekend, show,
4444
skip, stat, unsafe_read, unsafe_write, write, transcode, uv_error,
45-
rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize
45+
setup_stdio, rawhandle, OS_HANDLE, INVALID_OS_HANDLE, windowserror, filesize
4646

4747
import .Base.RefValue
4848

@@ -76,6 +76,7 @@ if OS_HANDLE !== RawFD
7676
end
7777

7878
rawhandle(file::File) = file.handle
79+
setup_stdio(file::File, ::Bool) = (file, false)
7980

8081
# Filesystem.open, not Base.open
8182
function open(path::AbstractString, flags::Integer, mode::Integer=0)

base/process.jl

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,28 @@ const SpawnIOs = Vector{Any} # convenience name for readability
7474
# handle marshalling of `Cmd` arguments from Julia to C
7575
@noinline function _spawn_primitive(file, cmd::Cmd, stdio::SpawnIOs)
7676
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
9799
if err != 0
98100
ccall(:jl_forceclose_uv, Cvoid, (Ptr{Cvoid},), handle) # will call free on handle eventually
99101
throw(_UVError("could not spawn " * repr(cmd), err))
@@ -209,10 +211,10 @@ function setup_stdio(stdio::PipeEndpoint, child_readable::Bool)
209211
rd, wr = link_pipe(!child_readable, child_readable)
210212
try
211213
open_pipe!(stdio, child_readable ? wr : rd)
212-
catch ex
214+
catch
213215
close_pipe_sync(rd)
214216
close_pipe_sync(wr)
215-
rethrow(ex)
217+
rethrow()
216218
end
217219
child = child_readable ? rd : wr
218220
return (child, true)
@@ -251,18 +253,18 @@ function setup_stdio(stdio::FileRedirect, child_readable::Bool)
251253
return (io, true)
252254
end
253255

254-
# incrementally move data between an IOBuffer and a system Pipe
256+
# incrementally move data between an arbitrary IO and a system Pipe
255257
# TODO: probably more efficient (when valid) to use `stdio` directly as the
256258
# 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)
258260
parent = PipeEndpoint()
259261
rd, wr = link_pipe(!child_readable, child_readable)
260262
try
261263
open_pipe!(parent, child_readable ? wr : rd)
262-
catch ex
264+
catch
263265
close_pipe_sync(rd)
264266
close_pipe_sync(wr)
265-
rethrow(ex)
267+
rethrow()
266268
end
267269
child = child_readable ? rd : wr
268270
try
@@ -271,24 +273,18 @@ function setup_stdio(stdio::Union{IOBuffer, BufferStream}, child_readable::Bool)
271273
@async try
272274
write(in, out)
273275
catch ex
274-
@warn "Process error" exception=(ex, catch_backtrace())
276+
@warn "Process I/O error" exception=(ex, catch_backtrace())
275277
finally
276278
close(parent)
277279
end
278280
end
279-
catch ex
281+
catch
280282
close_pipe_sync(child)
281-
rethrow(ex)
283+
rethrow()
282284
end
283285
return (child, true)
284286
end
285287

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-
292288
close_stdio(stdio::OS_HANDLE) = close_pipe_sync(stdio)
293289
close_stdio(stdio) = close(stdio)
294290

base/stream.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ end
282282
lock(s::LibuvStream) = lock(s.lock)
283283
unlock(s::LibuvStream) = unlock(s.lock)
284284

285+
setup_stdio(stream::LibuvStream) = (stream, false)
285286
rawhandle(stream::LibuvStream) = stream.handle
286287
unsafe_convert(::Type{Ptr{Cvoid}}, s::Union{LibuvStream, LibuvServer}) = s.handle
287288

test/spawn.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,15 @@ let text = "input-test-text"
697697
@test read(proc, String) == string(length(text), '\n')
698698
@test success(proc)
699699
@test String(take!(b)) == text
700+
701+
out = PipeBuffer()
702+
proc = run(catcmd, IOBuffer(SubString(text)), out)
703+
@test success(proc)
704+
@test proc.out === proc.err === proc.in === devnull
705+
@test String(take!(out)) == text
700706
end
707+
708+
701709
@test repr(Base.CmdRedirect(``, devnull, 0, false)) == "pipeline(``, stdin>Base.DevNull())"
702710
@test repr(Base.CmdRedirect(``, devnull, 1, true)) == "pipeline(``, stdout<Base.DevNull())"
703711
@test repr(Base.CmdRedirect(``, devnull, 11, true)) == "pipeline(``, 11<Base.DevNull())"

0 commit comments

Comments
 (0)