1
1
mirror of https://github.com/walles/moar.git synced 2024-09-11 12:15:43 +03:00

Merge pull request #215 from walles/johan/reprint-after-close-stdin

Fix crash on --quit-if-one-screen by dupping stdout
This commit is contained in:
Johan Walles 2024-06-24 07:31:16 +02:00 committed by GitHub
commit a9641512e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 4 deletions

View File

@ -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)

View File

@ -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

View File

@ -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