Browse Source

Simplify the juliac compatible fork-exec

This patch simplifies the juliac compatible pipe-fork-exec
implementation for running git on the formatted text. Instead of
collecting all bytes and then writing to stderr we instead write
directly from the intermediate buffer to stderr. The drawback is that if
reading bytes fail we might have already written something to stderr,
but this should rarely, if ever, happen under normal circumstances.
pull/57/head
Fredrik Ekre 1 year ago
parent
commit
8d011ec425
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 26
      src/juliac.jl

26
src/juliac.jl

@ -130,9 +130,7 @@ function run_juliac(cmd::Base.CmdRedirect)
argv = cmd′′.exec argv = cmd′′.exec
dir = cmd′′.dir dir = cmd′′.dir
# Run the command # Run the command
bytes = pipe_fork_exec(argv, dir) pipe_fork_exec(argv, dir)
# Write output
write(Core.stderr, bytes)
return return
end end
@ -145,6 +143,7 @@ end
function pipe_fork_exec(argv::Vector{String}, dir::String) function pipe_fork_exec(argv::Vector{String}, dir::String)
local pipe, fork, dup2, chdir, execv, waitpid # Silence of the Langs(erver) local pipe, fork, dup2, chdir, execv, waitpid # Silence of the Langs(erver)
STDOUT_FILENO, STDERR_FILENO = 1, 2
# Set up the pipe # Set up the pipe
fds = Vector{Cint}(undef, 2) fds = Vector{Cint}(undef, 2)
READ_END, WRITE_END = 1, 2 READ_END, WRITE_END = 1, 2
@ -161,7 +160,6 @@ function pipe_fork_exec(argv::Vector{String}, dir::String)
err = @ccall close(fds[READ_END]::Cint)::Cint err = @ccall close(fds[READ_END]::Cint)::Cint
err == -1 && systemerror("close") err == -1 && systemerror("close")
# Duplicate write end of the pipe to stdout and stderr # Duplicate write end of the pipe to stdout and stderr
STDOUT_FILENO, STDERR_FILENO = 1, 2
err = @ccall dup2(fds[WRITE_END]::Cint, STDOUT_FILENO::Cint)::Cint err = @ccall dup2(fds[WRITE_END]::Cint, STDOUT_FILENO::Cint)::Cint
err == -1 && systemerror("dup2") err == -1 && systemerror("dup2")
err = @ccall dup2(fds[WRITE_END]::Cint, STDERR_FILENO::Cint)::Cint err = @ccall dup2(fds[WRITE_END]::Cint, STDERR_FILENO::Cint)::Cint
@ -180,18 +178,24 @@ function pipe_fork_exec(argv::Vector{String}, dir::String)
# Close write end of the pipe # Close write end of the pipe
err = @ccall close(fds[WRITE_END]::Cint)::Cint err = @ccall close(fds[WRITE_END]::Cint)::Cint
err == -1 && systemerror("close") err == -1 && systemerror("close")
bytes = UInt8[] # Shuffle bytes from the pipe to stderr
buf = Vector{UInt8}(undef, 1024) bufsize = 1024
buf = Vector{UInt8}(undef, bufsize)
while true while true
nread = @ccall read(fds[READ_END]::Cint, buf::Ptr{Cvoid}, 1024::Csize_t)::Cssize_t # Read bytes from the pipe
nread = @ccall read(fds[READ_END]::Cint, buf::Ptr{Cvoid}, bufsize::Csize_t)::Cssize_t
nread == -1 && systemerror("read") nread == -1 && systemerror("read")
nread == 0 && break # eof nread == 0 && break # eof
append!(bytes, @view(buf[1:nread])) # Write bytes to stderr
nwrite = @ccall write(STDERR_FILENO::Cint, buf::Ptr{Cvoid}, nread::Csize_t)::Cssize_t
nread == -1 && systemerror("write")
@assert nwrite == nread
end end
err = @ccall close(fds[READ_END]::Cint)::Cint # Close the read end of the pipe # Close the read end of the pipe
err = @ccall close(fds[READ_END]::Cint)::Cint
err == -1 && systemerror("close") err == -1 && systemerror("close")
# Check exit status of the child # Wait for, and check exit status of, the child
status = Ref{Cint}() status = Ref{Cint}()
wpid = @ccall waitpid(cpid::Cint, status::Ref{Cint}, 0::Cint)::Cint wpid = @ccall waitpid(cpid::Cint, status::Ref{Cint}, 0::Cint)::Cint
wpid == -1 && systemerror("waitpid") wpid == -1 && systemerror("waitpid")
@ -199,5 +203,5 @@ function pipe_fork_exec(argv::Vector{String}, dir::String)
error("child process did not exit normally") error("child process did not exit normally")
end end
# crc = WEXITSTATUS(status) # ignore this like `ignorestatus(cmd)` # crc = WEXITSTATUS(status) # ignore this like `ignorestatus(cmd)`
return bytes return
end end

Loading…
Cancel
Save