From c88f4c064556b867ec1a3460ab9f8820453cef18 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Mon, 6 Sep 2021 22:27:43 -0700 Subject: [PATCH 1/4] Use raw block to return tty to proper state --- Library/Homebrew/sandbox.rb | 56 +++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index a389505b0f..6da03d102d 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -101,32 +101,40 @@ class Sandbox command = [SANDBOX_EXEC, "-f", seatbelt.path, *args] # Start sandbox in a pseudoterminal to prevent access of the parent terminal. T.unsafe(PTY).spawn(*command) do |r, w, pid| - # Set the PTY's window size to match the parent terminal. - # Some formula tests are sensitive to the terminal size and fail if this is not set. - winch = proc do |_sig| - w.winsize = if $stdout.tty? - # We can only use IO#winsize if the IO object is a TTY. - $stdout.winsize - else - # Otherwise, default to tput, if available. - # This relies on ncurses rather than the system's ioctl. - [Utils.popen_read("tput", "lines").to_i, Utils.popen_read("tput", "cols").to_i] + write_to_pty = proc { + # Set the PTY's window size to match the parent terminal. + # Some formula tests are sensitive to the terminal size and fail if this is not set. + winch = proc do |_sig| + w.winsize = if $stdout.tty? + # We can only use IO#winsize if the IO object is a TTY. + $stdout.winsize + else + # Otherwise, default to tput, if available. + # This relies on ncurses rather than the system's ioctl. + [Utils.popen_read("tput", "lines").to_i, Utils.popen_read("tput", "cols").to_i] + end end + + begin + # Update the window size whenever the parent terminal's window size changes. + old_winch = trap(:WINCH, &winch) + winch.call(nil) + + stdin_thread = Thread.new { IO.copy_stream($stdin, w) } + + r.each_char { |c| print(c) } + + Process.wait(pid) + ensure + stdin_thread&.kill + trap(:WINCH, old_winch) + end + } + if $stdout.tty? + $stdin.raw &write_to_pty + else + write_to_pty.call end - # Update the window size whenever the parent terminal's window size changes. - old_winch = trap(:WINCH, &winch) - winch.call(nil) - - $stdin.raw! if $stdin.tty? - stdin_thread = Thread.new { IO.copy_stream($stdin, w) } - - r.each_char { |c| print(c) } - - Process.wait(pid) - ensure - stdin_thread&.kill - $stdin.cooked! if $stdin.tty? - trap(:WINCH, old_winch) end raise ErrorDuringExecution.new(command, status: $CHILD_STATUS) unless $CHILD_STATUS.success? rescue From c7b36df8794969c5fb19b326d0586effff3bf83f Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Tue, 7 Sep 2021 09:44:58 -0700 Subject: [PATCH 2/4] Fix style --- Library/Homebrew/sandbox.rb | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index 6da03d102d..fd3b90ba9b 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -101,20 +101,20 @@ class Sandbox command = [SANDBOX_EXEC, "-f", seatbelt.path, *args] # Start sandbox in a pseudoterminal to prevent access of the parent terminal. T.unsafe(PTY).spawn(*command) do |r, w, pid| - write_to_pty = proc { - # Set the PTY's window size to match the parent terminal. - # Some formula tests are sensitive to the terminal size and fail if this is not set. - winch = proc do |_sig| - w.winsize = if $stdout.tty? - # We can only use IO#winsize if the IO object is a TTY. - $stdout.winsize - else - # Otherwise, default to tput, if available. - # This relies on ncurses rather than the system's ioctl. - [Utils.popen_read("tput", "lines").to_i, Utils.popen_read("tput", "cols").to_i] - end + # Set the PTY's window size to match the parent terminal. + # Some formula tests are sensitive to the terminal size and fail if this is not set. + winch = proc do |_sig| + w.winsize = if $stdout.tty? + # We can only use IO#winsize if the IO object is a TTY. + $stdout.winsize + else + # Otherwise, default to tput, if available. + # This relies on ncurses rather than the system's ioctl. + [Utils.popen_read("tput", "lines").to_i, Utils.popen_read("tput", "cols").to_i] end + end + write_to_pty = proc do begin # Update the window size whenever the parent terminal's window size changes. old_winch = trap(:WINCH, &winch) @@ -129,9 +129,10 @@ class Sandbox stdin_thread&.kill trap(:WINCH, old_winch) end - } - if $stdout.tty? - $stdin.raw &write_to_pty + end + + if $stdin.tty? + $stdin.raw(&write_to_pty) else write_to_pty.call end From 1f0f08c30d418356b0378f5460647e3425653204 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Tue, 7 Sep 2021 11:15:06 -0700 Subject: [PATCH 3/4] Remove redundant begin --- Library/Homebrew/sandbox.rb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index fd3b90ba9b..ce7549e7f3 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -115,20 +115,18 @@ class Sandbox end write_to_pty = proc do - begin - # Update the window size whenever the parent terminal's window size changes. - old_winch = trap(:WINCH, &winch) - winch.call(nil) + # Update the window size whenever the parent terminal's window size changes. + old_winch = trap(:WINCH, &winch) + winch.call(nil) - stdin_thread = Thread.new { IO.copy_stream($stdin, w) } + stdin_thread = Thread.new { IO.copy_stream($stdin, w) } - r.each_char { |c| print(c) } + r.each_char { |c| print(c) } - Process.wait(pid) - ensure - stdin_thread&.kill - trap(:WINCH, old_winch) - end + Process.wait(pid) + ensure + stdin_thread&.kill + trap(:WINCH, old_winch) end if $stdin.tty? From c0de9c54976d528ac97908d5bc3dadf18473b152 Mon Sep 17 00:00:00 2001 From: Sean Sullivan Date: Tue, 7 Sep 2021 19:49:01 -0700 Subject: [PATCH 4/4] Comment more thoroughly --- Library/Homebrew/sandbox.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Library/Homebrew/sandbox.rb b/Library/Homebrew/sandbox.rb index ce7549e7f3..9e30f01657 100644 --- a/Library/Homebrew/sandbox.rb +++ b/Library/Homebrew/sandbox.rb @@ -130,6 +130,10 @@ class Sandbox end if $stdin.tty? + # If stdin is a TTY, use io.raw to set stdin to a raw, passthrough + # mode while we copy the input/output of the process spawned in the + # PTY. After we've finished copying to/from the PTY process, io.raw + # will restore the stdin TTY to its original state. $stdin.raw(&write_to_pty) else write_to_pty.call