Skip to content

Commit

Permalink
pty_{master,slave} -> pt{m,s} (JuliaLang#36315)
Browse files Browse the repository at this point in the history
We decided to get rid of the master/slave terminology in Julia in JuliaLang#30058.
However, we decided to keep it for PTYs, where the terminology is imposed
upon us by POSIX (and thus changing it would be confusing for people who
might need to read up on the POSIX definitions of these concepts). It
was recently suggested to revisit this, by renaming to ptm and pts instead,
which also fit well (as the devies that the fds refer to are `/dev/ptmx`
and `/dev/pts` respectively), are googleable (`pty pts` will yield the
correct man page) and will probably need to remain even if POSIX
adjusts their terminology, since they're part of the ABI (presumably
they'll be backronymed to whatever terminology ends up winning).
This patch does this rename.
  • Loading branch information
Keno committed Jun 17, 2020
1 parent 0a2644a commit bf3ed57
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 55 deletions.
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

0 comments on commit bf3ed57

Please sign in to comment.