Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pty_{master,slave} -> pt{m,s} #36315

Merged
merged 1 commit into from
Jun 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions contrib/generate_precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function generate_precompile_statements()

mktemp() do precompile_file, precompile_file_h
# Run a repl process and replay our script
pty_slave, pty_master = open_fake_pty()
pts, ptm = open_fake_pty()
blackhole = Sys.isunix() ? "/dev/null" : "nul"
if have_repl
cmdargs = ```--color=yes
Expand All @@ -104,25 +104,25 @@ function generate_precompile_statements()
--cpu-target=native --startup-file=no --color=yes
-e 'import REPL; REPL.Terminals.is_precompiling[] = true'
-i $cmdargs```,
pty_slave, pty_slave, pty_slave; wait=false)
pts, pts, pts; wait=false)
end
Base.close_stdio(pty_slave)
# Prepare a background process to copy output from process until `pty_slave` is closed
Base.close_stdio(pts)
# Prepare a background process to copy output from process until `pts` is closed
output_copy = Base.BufferStream()
tee = @async try
while !eof(pty_master)
l = readavailable(pty_master)
while !eof(ptm)
l = readavailable(ptm)
write(debug_output, l)
Sys.iswindows() && (sleep(0.1); yield(); yield()) # workaround hang - probably a libuv issue?
write(output_copy, l)
end
close(output_copy)
close(pty_master)
close(ptm)
catch ex
close(output_copy)
close(pty_master)
close(ptm)
if !(ex isa Base.IOError && ex.code == Base.UV_EIO)
rethrow() # ignore EIO on pty_master after pty_slave dies
rethrow() # ignore EIO on ptm after pts dies
end
end
# wait for the definitive prompt before start writing to the TTY
Expand All @@ -141,7 +141,7 @@ function generate_precompile_statements()
bytesavailable(output_copy) > 0 && readavailable(output_copy)
# push our input
write(debug_output, "\n#### inputting statement: ####\n$(repr(l))\n####\n")
write(pty_master, l, "\n")
write(ptm, l, "\n")
readuntil(output_copy, "\n")
# wait for the next prompt-like to appear
# NOTE: this is rather innaccurate because the Pkg REPL mode is a special flower
Expand All @@ -150,10 +150,10 @@ function generate_precompile_statements()
end
println()
end
write(pty_master, "exit()\n")
write(ptm, "exit()\n")
wait(tee)
success(p) || Base.pipeline_error(p)
close(pty_master)
close(ptm)
write(debug_output, "\n#### FINISHED ####\n")

# Extract the precompile statements from the precompile file
Expand Down
18 changes: 9 additions & 9 deletions stdlib/LibGit2/test/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ function challenge_prompt(cmd::Cmd, challenges; timeout::Integer=60, debug::Bool
return "Process output found:\n\"\"\"\n$str\n\"\"\""
end
out = IOBuffer()
with_fake_pty() do pty_slave, pty_master
p = run(detach(cmd), pty_slave, pty_slave, pty_slave, wait=false)
Base.close_stdio(pty_slave)
with_fake_pty() do pts, ptm
p = run(detach(cmd), pts, pts, pts, wait=false)
Base.close_stdio(pts)

# Kill the process if it takes too long. Typically occurs when process is waiting
# for input.
Expand Down Expand Up @@ -79,25 +79,25 @@ function challenge_prompt(cmd::Cmd, challenges; timeout::Integer=60, debug::Bool
end

for (challenge, response) in challenges
write(out, readuntil(pty_master, challenge, keep=true))
if !isopen(pty_master)
write(out, readuntil(ptm, challenge, keep=true))
if !isopen(ptm)
error("Could not locate challenge: \"$challenge\". ",
format_output(out))
end
write(pty_master, response)
write(ptm, response)
end

# Capture output from process until `pty_slave` is closed
# Capture output from process until `pts` is closed
try
write(out, pty_master)
write(out, ptm)
catch ex
if !(ex isa Base.IOError && ex.code == Base.UV_EIO)
rethrow() # ignore EIO from master after slave dies
end
end

status = fetch(timer)
close(pty_master)
close(ptm)
if status != :success
if status == :timeout
error("Process timed out possibly waiting for a response. ",
Expand Down
26 changes: 13 additions & 13 deletions stdlib/REPL/test/repl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -768,43 +768,43 @@ Base.exit_on_sigint(true)

let exename = Base.julia_cmd()
# Test REPL in dumb mode
with_fake_pty() do pty_slave, pty_master
with_fake_pty() do pts, ptm
nENV = copy(ENV)
nENV["TERM"] = "dumb"
p = run(detach(setenv(`$exename --startup-file=no -q`, nENV)), pty_slave, pty_slave, pty_slave, wait=false)
Base.close_stdio(pty_slave)
output = readuntil(pty_master, "julia> ", keep=true)
p = run(detach(setenv(`$exename --startup-file=no -q`, nENV)), pts, pts, pts, wait=false)
Base.close_stdio(pts)
output = readuntil(ptm, "julia> ", keep=true)
if ccall(:jl_running_on_valgrind, Cint,()) == 0
# If --trace-children=yes is passed to valgrind, we will get a
# valgrind banner here, not just the prompt.
@test output == "julia> "
end
write(pty_master, "1\nexit()\n")
write(ptm, "1\nexit()\n")

output = readuntil(pty_master, ' ', keep=true)
output = readuntil(ptm, ' ', keep=true)
if Sys.iswindows()
# Our fake pty is actually a pipe, and thus lacks the input echo feature of posix
@test output == "1\n\njulia> "
else
@test output == "1\r\nexit()\r\n1\r\n\r\njulia> "
end
@test bytesavailable(pty_master) == 0
@test bytesavailable(ptm) == 0
@test if Sys.iswindows() || Sys.isbsd()
eof(pty_master)
eof(ptm)
else
# Some platforms (such as linux) report EIO instead of EOF
# possibly consume child-exited notification
# for example, see discussion in https://bugs.python.org/issue5380
try
eof(pty_master) && !Sys.islinux()
eof(ptm) && !Sys.islinux()
catch ex
(ex isa Base.IOError && ex.code == Base.UV_EIO) || rethrow()
@test_throws ex eof(pty_master) # make sure the error is sticky
pty_master.readerror = nothing
eof(pty_master)
@test_throws ex eof(ptm) # make sure the error is sticky
ptm.readerror = nothing
eof(ptm)
end
end
@test read(pty_master, String) == ""
@test read(ptm, String) == ""
wait(p)
end

Expand Down
42 changes: 21 additions & 21 deletions test/testhelpers/FakePTYs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@ function open_fake_pty()
pid = string(getpid(), base=16, pad=16)
pipename = """\\\\?\\pipe\\cygwin-$pid-pty10-abcdefg"""
server = listen(pipename)
pty_slave = connect(pipename)
@assert ccall(:jl_ispty, Cint, (Ptr{Cvoid},), pty_slave.handle) == 1
pty_master = accept(server)
pts = connect(pipename)
@assert ccall(:jl_ispty, Cint, (Ptr{Cvoid},), pts.handle) == 1
ptm = accept(server)
close(server)
# extract just the file descriptor
fds = Libc.dup(Base._fd(pty_slave))
close(pty_slave)
pty_slave = fds
# convert pty_slave handle to a TTY
#fds = pty_slave.handle
#pty_slave.status = Base.StatusClosed
#pty_slave.handle = C_NULL
#pty_slave = Base.TTY(fds, Base.StatusOpen)
fds = Libc.dup(Base._fd(pts))
close(pts)
pts = fds
# convert pts handle to a TTY
#fds = pts.handle
#pts.status = Base.StatusClosed
#pts.handle = C_NULL
#pts = Base.TTY(fds, Base.StatusOpen)
else
O_RDWR = Base.Filesystem.JL_O_RDWR
O_NOCTTY = Base.Filesystem.JL_O_NOCTTY

fdm = ccall(:posix_openpt, Cint, (Cint,), O_RDWR | O_NOCTTY)
fdm == -1 && error("Failed to open pty_master")
fdm == -1 && error("Failed to open ptm")
rc = ccall(:grantpt, Cint, (Cint,), fdm)
rc != 0 && error("grantpt failed")
rc = ccall(:unlockpt, Cint, (Cint,), fdm)
Expand All @@ -43,21 +43,21 @@ function open_fake_pty()
fds = ccall(:open, Cint, (Ptr{UInt8}, Cint),
ccall(:ptsname, Ptr{UInt8}, (Cint,), fdm), O_RDWR | O_NOCTTY)

pty_slave = RawFD(fds)
# pty_slave = fdio(fds, true)
# pty_slave = Base.Filesystem.File(RawFD(fds))
# pty_slave = Base.TTY(RawFD(fds); readable = false)
pty_master = Base.TTY(RawFD(fdm))
pts = RawFD(fds)
# pts = fdio(fds, true)
# pts = Base.Filesystem.File(RawFD(fds))
# pts = Base.TTY(RawFD(fds); readable = false)
ptm = Base.TTY(RawFD(fdm))
end
return pty_slave, pty_master
return pts, ptm
end

function with_fake_pty(f)
pty_slave, pty_master = open_fake_pty()
pts, ptm = open_fake_pty()
try
f(pty_slave, pty_master)
f(pts, ptm)
finally
close(pty_master)
close(ptm)
end
nothing
end
Expand Down