From 2a580f8ad4f8029919e9bcadd5ea2ad0598f49cf Mon Sep 17 00:00:00 2001 From: Jarrod Funnell Date: Tue, 4 Sep 2018 20:23:37 +1000 Subject: [PATCH 1/2] Use blocking IO on a TTY if it can't be reopened --- src/io/file_descriptor.cr | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/io/file_descriptor.cr b/src/io/file_descriptor.cr index 30ad23f5e192..0b26bb3dcaeb 100644 --- a/src/io/file_descriptor.cr +++ b/src/io/file_descriptor.cr @@ -27,12 +27,12 @@ class IO::FileDescriptor < IO path = uninitialized UInt8[256] if LibC.ttyname_r(fd, path, 256) == 0 # Open a fresh handle to the TTY - fd = LibC.open(path, LibC::O_RDWR) - - new(fd).tap(&.close_on_exec = true) - else - new(fd, blocking: true) + if (clone_fd = LibC.open(path, LibC::O_RDWR)) >= 0 + return new(clone_fd).tap(&.close_on_exec = true) + end end + # Fallback to blocking IO. + new(fd, blocking: true) end def blocking From 5e459d69961233f3cd1c4006ad4d0c73205eb4ef Mon Sep 17 00:00:00 2001 From: Jarrod Funnell Date: Wed, 5 Sep 2018 09:34:49 +1000 Subject: [PATCH 2/2] Simplify tty fallback logic --- src/io/file_descriptor.cr | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/io/file_descriptor.cr b/src/io/file_descriptor.cr index 0b26bb3dcaeb..a73b5fdbc26a 100644 --- a/src/io/file_descriptor.cr +++ b/src/io/file_descriptor.cr @@ -20,19 +20,18 @@ class IO::FileDescriptor < IO # :nodoc: def self.from_stdio(fd) - # If we have a TTY for stdin/out/err, it is a shared terminal. + # If we have a TTY for stdin/out/err, it is possibly a shared terminal. # We need to reopen it to use O_NONBLOCK without causing other programs to break # Figure out the terminal TTY name. If ttyname fails we have a non-tty, or something strange. path = uninitialized UInt8[256] - if LibC.ttyname_r(fd, path, 256) == 0 - # Open a fresh handle to the TTY - if (clone_fd = LibC.open(path, LibC::O_RDWR)) >= 0 - return new(clone_fd).tap(&.close_on_exec = true) - end - end - # Fallback to blocking IO. - new(fd, blocking: true) + ret = LibC.ttyname_r(fd, path, 256) + return new(fd, blocking: true) unless ret == 0 + + clone_fd = LibC.open(path, LibC::O_RDWR) + return new(fd, blocking: true) if clone_fd == -1 + + new(clone_fd).tap(&.close_on_exec = true) end def blocking