Skip to content

Commit

Permalink
Fix Process.exec stream redirection on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil committed Sep 7, 2024
1 parent 025f3e0 commit 9c63f82
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
26 changes: 15 additions & 11 deletions src/crystal/system/win32/process.cr
Original file line number Diff line number Diff line change
Expand Up @@ -367,20 +367,24 @@ struct Crystal::System::Process
end
end

# Replaces the C standard streams' file descriptors, not Win32's, since
# `try_replace` uses the C `LibC._wexecvp` and only cares about the former
private def self.reopen_io(src_io : IO::FileDescriptor, dst_io : IO::FileDescriptor)
src_io = to_real_fd(src_io)
unless src_io.system_blocking?
raise IO::Error.new("Non-blocking streams are not supported in `Process.exec`", target: src_io)
end

dst_io.reopen(src_io)
dst_io.blocking = true
dst_io.close_on_exec = false
end
dst_fd =
case dst_io
when ORIGINAL_STDIN then 0
when ORIGINAL_STDOUT then 1
when ORIGINAL_STDERR then 2
else
raise "BUG: Invalid destination IO"
end

private def self.to_real_fd(fd : IO::FileDescriptor)
case fd
when STDIN then ORIGINAL_STDIN
when STDOUT then ORIGINAL_STDOUT
when STDERR then ORIGINAL_STDERR
else fd
if LibC._dup2(LibC._open_osfhandle(src_io.windows_handle, 0), dst_fd) == -1
raise RuntimeError.from_errno("Failed to replace C file descriptor")
end
end

Expand Down
4 changes: 2 additions & 2 deletions src/lib_c/x86_64-windows-msvc/c/io.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ require "c/stdint"

lib LibC
fun _wexecvp(cmdname : WCHAR*, argv : WCHAR**) : IntPtrT
fun _open_osfhandle(osfhandle : HANDLE, flags : LibC::Int) : LibC::Int
fun _dup2(fd1 : Int, fd2 : Int) : Int

# unused
fun _open_osfhandle(osfhandle : HANDLE, flags : LibC::Int) : LibC::Int
fun _get_osfhandle(fd : Int) : IntPtrT
fun _close(fd : Int) : Int
fun _dup2(fd1 : Int, fd2 : Int) : Int
fun _isatty(fd : Int) : Int
fun _write(fd : Int, buffer : UInt8*, count : UInt) : Int
fun _read(fd : Int, buffer : UInt8*, count : UInt) : Int
Expand Down

0 comments on commit 9c63f82

Please sign in to comment.