Skip to content

Commit

Permalink
Merge pull request #215 from walles/johan/reprint-after-close-stdin
Browse files Browse the repository at this point in the history
Fix crash on --quit-if-one-screen by dupping stdout
  • Loading branch information
walles committed Jun 24, 2024
2 parents e73a70a + 69bef30 commit a964151
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
1 change: 1 addition & 0 deletions moar.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ func printProblemsHeader() {
fmt.Fprintln(os.Stderr, "Version:", versionString)
fmt.Fprintln(os.Stderr, "LANG :", os.Getenv("LANG"))
fmt.Fprintln(os.Stderr, "TERM :", os.Getenv("TERM"))
fmt.Fprintln(os.Stderr, "MOAR :", os.Getenv("MOAR"))
fmt.Fprintln(os.Stderr)
fmt.Fprintln(os.Stderr, "GOOS :", runtime.GOOS)
fmt.Fprintln(os.Stderr, "GOARCH :", runtime.GOARCH)
Expand Down
7 changes: 7 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ echo Testing not crashing with different argument orders...
./moar --trace +123 moar.go >/dev/null
./moar --trace moar.go +123 >/dev/null

# We can only do this test if we have a terminal. This means it will be run
# locally but not in CI. Not great, but better than nothing.
if [[ -t 1 ]]; then
echo Test auto quitting on single screen...
echo " (success)" | ./moar --quit-if-one-screen
fi

echo Test decompressing while piping
# Related to https://github.com/walles/moar/issues/177
./moar sample-files/compressed.txt.gz | grep compressed >/dev/null
Expand Down
17 changes: 13 additions & 4 deletions twin/screen-setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,27 @@ func (screen *UnixScreen) setupSigwinchNotification() {
}

func (screen *UnixScreen) setupTtyInTtyOut() error {
// Dup stdout so we can close stdin in Close() without closing stdout.
// Before this dupping, we crashed on using --quit-if-one-screen.
//
// Ref:https://github.com/walles/moar/issues/214
stdoutDupFd, err := syscall.Dup(int(os.Stdout.Fd()))
if err != nil {
return err
}
stdoutDup := os.NewFile(uintptr(stdoutDupFd), "moar-stdout-dup")

// os.Stdout is a stream that goes to our terminal window.
//
// So if we read from there, we'll get input from the terminal window.
//
// Reading from os.Stdin will fail if we're getting data piped into
// ourselves from some other command.
// If we just read from os.Stdin that would fail if we're getting data piped
// into ourselves from some other command.
//
// Tested on macOS and Linux, works like a charm!
screen.ttyIn = os.Stdout // <- YES, WE SHOULD ASSIGN STDOUT TO TTYIN
screen.ttyIn = stdoutDup // <- YES, WE SHOULD ASSIGN STDOUT TO TTYIN

// Set input stream to raw mode
var err error
screen.oldTerminalState, err = term.MakeRaw(int(screen.ttyIn.Fd()))
if err != nil {
return err
Expand Down

0 comments on commit a964151

Please sign in to comment.