From f80b07b2c85af2f3dbfec5a1cad47e826c4b80f0 Mon Sep 17 00:00:00 2001 From: greatroar <@> Date: Tue, 13 Oct 2020 12:56:23 +0200 Subject: [PATCH] Fix IsProcessBackground on Linux with stdin redirection The previous implementation assumed that stdin was a terminal. It now checks the terminal's fd. --- internal/ui/termstatus/background.go | 2 +- internal/ui/termstatus/background_linux.go | 24 ++++++++++--------- .../ui/termstatus/background_linux_test.go | 19 +++++++++++++++ internal/ui/termstatus/status.go | 6 ++--- 4 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 internal/ui/termstatus/background_linux_test.go diff --git a/internal/ui/termstatus/background.go b/internal/ui/termstatus/background.go index e371c18df..8c1e9f162 100644 --- a/internal/ui/termstatus/background.go +++ b/internal/ui/termstatus/background.go @@ -4,6 +4,6 @@ package termstatus // IsProcessBackground reports whether the current process is running in the // background. Not implemented for this platform. -func IsProcessBackground() bool { +func IsProcessBackground(uintptr) bool { return false } diff --git a/internal/ui/termstatus/background_linux.go b/internal/ui/termstatus/background_linux.go index f99091128..2c32faf17 100644 --- a/internal/ui/termstatus/background_linux.go +++ b/internal/ui/termstatus/background_linux.go @@ -1,21 +1,23 @@ package termstatus import ( - "syscall" - "unsafe" - "github.com/restic/restic/internal/debug" + + "golang.org/x/sys/unix" ) -// IsProcessBackground reports whether the current process is running in the background. -func IsProcessBackground() bool { - var pid int - _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&pid))) - - if err != 0 { +// IsProcessBackground reports whether the current process is running in the +// background. fd must be a file descriptor for the terminal. +func IsProcessBackground(fd uintptr) bool { + bg, err := isProcessBackground(fd) + if err != nil { debug.Log("Can't check if we are in the background. Using default behaviour. Error: %s\n", err.Error()) return false } - - return pid != syscall.Getpgrp() + return bg +} + +func isProcessBackground(fd uintptr) (bool, error) { + pid, err := unix.IoctlGetInt(int(fd), unix.TIOCGPGRP) + return pid != unix.Getpgrp(), err } diff --git a/internal/ui/termstatus/background_linux_test.go b/internal/ui/termstatus/background_linux_test.go new file mode 100644 index 000000000..0880d2bc0 --- /dev/null +++ b/internal/ui/termstatus/background_linux_test.go @@ -0,0 +1,19 @@ +package termstatus + +import ( + "os" + "testing" + + rtest "github.com/restic/restic/internal/test" +) + +func TestIsProcessBackground(t *testing.T) { + tty, err := os.Open("/dev/tty") + if err != nil { + t.Skipf("can't open terminal: %v", err) + } + defer tty.Close() + + _, err = isProcessBackground(tty.Fd()) + rtest.OK(t, err) +} diff --git a/internal/ui/termstatus/status.go b/internal/ui/termstatus/status.go index c1648206b..87cf1a232 100644 --- a/internal/ui/termstatus/status.go +++ b/internal/ui/termstatus/status.go @@ -95,7 +95,7 @@ func (t *Terminal) run(ctx context.Context) { for { select { case <-ctx.Done(): - if IsProcessBackground() { + if IsProcessBackground(t.fd) { // ignore all messages, do nothing, we are in the background process group continue } @@ -104,7 +104,7 @@ func (t *Terminal) run(ctx context.Context) { return case msg := <-t.msg: - if IsProcessBackground() { + if IsProcessBackground(t.fd) { // ignore all messages, do nothing, we are in the background process group continue } @@ -136,7 +136,7 @@ func (t *Terminal) run(ctx context.Context) { } case stat := <-t.status: - if IsProcessBackground() { + if IsProcessBackground(t.fd) { // ignore all messages, do nothing, we are in the background process group continue }