From 8034ac37f89f8ff952c1d22edaf69cbe5c5ffdb3 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Tue, 18 Apr 2023 02:31:00 +0800 Subject: [PATCH 1/2] Allow `/SUBSYSTEM:WINDOWS` on Windows --- src/crystal/system/win32/file_descriptor.cr | 23 ++++++++++++++------- src/crystal/system/win32/process.cr | 4 +--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index f9c0d525bc72..4292dca12ab7 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -54,8 +54,18 @@ module Crystal::System::FileDescriptor end private def windows_handle + FileDescriptor.windows_handle!(fd) + end + + def self.windows_handle(fd) + ret = LibC._get_osfhandle(fd) + return LibC::INVALID_HANDLE_VALUE if ret == -1 || ret == -2 + LibC::HANDLE.new(ret) + end + + def self.windows_handle!(fd) ret = LibC._get_osfhandle(fd) - raise RuntimeError.from_errno("_get_osfhandle") if ret == -1 + raise RuntimeError.from_errno("_get_osfhandle") if ret == -1 || ret == -2 LibC::HANDLE.new(ret) end @@ -154,9 +164,7 @@ module Crystal::System::FileDescriptor end def self.pread(fd, buffer, offset) - handle = LibC._get_osfhandle(fd) - raise IO::Error.from_errno("_get_osfhandle") if handle == -1 - handle = LibC::HANDLE.new(handle) + handle = windows_handle!(fd) overlapped = LibC::OVERLAPPED.new overlapped.union.offset.offset = LibC::DWORD.new(offset) @@ -172,9 +180,8 @@ module Crystal::System::FileDescriptor def self.from_stdio(fd) console_handle = false - handle = LibC._get_osfhandle(fd) - if handle != -1 - handle = LibC::HANDLE.new(handle) + handle = windows_handle(fd) + if handle != LibC::INVALID_HANDLE_VALUE # TODO: use `out old_mode` after implementing interpreter out closured var old_mode = uninitialized LibC::DWORD if LibC.GetConsoleMode(handle, pointerof(old_mode)) != 0 @@ -187,7 +194,7 @@ module Crystal::System::FileDescriptor end end - io = IO::FileDescriptor.new(fd) + io = IO::FileDescriptor.new(fd, blocking: true) # Set sync or flush_on_newline as described in STDOUT and STDERR docs. # See https://crystal-lang.org/api/toplevel.html#STDERR if console_handle diff --git a/src/crystal/system/win32/process.cr b/src/crystal/system/win32/process.cr index b887d8521c46..a9bb85e9aa5a 100644 --- a/src/crystal/system/win32/process.cr +++ b/src/crystal/system/win32/process.cr @@ -182,9 +182,7 @@ struct Crystal::System::Process end private def self.handle_from_io(io : IO::FileDescriptor, parent_io) - ret = LibC._get_osfhandle(io.fd) - raise RuntimeError.from_winerror("_get_osfhandle") if ret == -1 - source_handle = LibC::HANDLE.new(ret) + source_handle = FileDescriptor.windows_handle!(io.fd) cur_proc = LibC.GetCurrentProcess if LibC.DuplicateHandle(cur_proc, source_handle, cur_proc, out new_handle, 0, true, LibC::DUPLICATE_SAME_ACCESS) == 0 From 5491612aa754786f9e18a3b728eaf747e08459cc Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Tue, 18 Apr 2023 02:51:36 +0800 Subject: [PATCH 2/2] `-2` does not set errno --- src/crystal/system/win32/file_descriptor.cr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index 4292dca12ab7..576fb64e53c8 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -65,7 +65,8 @@ module Crystal::System::FileDescriptor def self.windows_handle!(fd) ret = LibC._get_osfhandle(fd) - raise RuntimeError.from_errno("_get_osfhandle") if ret == -1 || ret == -2 + raise RuntimeError.from_errno("_get_osfhandle") if ret == -1 + raise RuntimeError.new("_get_osfhandle returned -2") if ret == -2 LibC::HANDLE.new(ret) end