Skip to content

Instantly share code, notes, and snippets.

@glyph
Created March 5, 2015 22:53
Show Gist options
  • Save glyph/2c9660f469a612bac9e4 to your computer and use it in GitHub Desktop.
Save glyph/2c9660f469a612bac9e4 to your computer and use it in GitHub Desktop.
created by github.com/tr3buchet/gister
# This is a stripped-down example based on Selecta's TTY handling. We store the
# TTY state in `tty_state`, then go into an infinite loop. When the loop is
# terminated by a ^C, we try to restore the TTY state. It's important that this
# work, but it doesn't in some subtle situations, and I don't know why.
#
# Save this file as test.rb and run it via this command, where `stty` should
# successfully restore the TTY state:
# bash -c 'echo | ruby test.rb'
#
# Next, run it via this command, where `stty` should fail to restore the TTY
# state:
# bash -c 'echo $(echo | ruby test.rb)'
#
# Clearly, the command substitution matters, but I don't know why. Initially, I
# thought that the TTY file might be gone by the time the SIGINT is sent,
# meaning there would be nothing for `stty` to see. However, you can see that
# in both commands the TTY file is still there.
#
# Here's what I get when I run those two commands and ^C them (on OS X 10.10,
# but this problem was originally observed in Linux):
#
# $ bash -c 'echo | ruby test.rb'
# ^C
# Did stty succeed?: true
# Is /dev/tty still there?: true
#
# $ bash -c 'echo $(echo | ruby test.rb)'
# ^C
# stty: tcsetattr: Input/output error
#
# Did stty succeed?: false
# Is /dev/tty still there?: true
tty_state = `stty -f /dev/tty -g`
begin
loop do end
rescue Interrupt
# Swallow the exception
ensure
$stderr.puts `sleep 1s; stty -f /dev/tty #{tty_state}`
$stderr.puts "Did stty succeed?: #{$?.success?}"
$stderr.puts "Is /dev/tty still there?: #{!open("/dev/tty", "w").closed?}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment