From 0b3184a5acb68043a6cf44b7c223d84d8badd930 Mon Sep 17 00:00:00 2001 From: Doug Rabson Date: Fri, 26 Aug 2022 15:32:52 +0100 Subject: pkg/domain: Add terminal support for FreeBSD This just moves the code to files which can be shared with freebsd. [NO NEW TESTS NEEDED] Signed-off-by: Doug Rabson --- pkg/domain/infra/abi/terminal/sigproxy_commn.go | 63 ++++++++++++ pkg/domain/infra/abi/terminal/sigproxy_linux.go | 60 ----------- pkg/domain/infra/abi/terminal/terminal_common.go | 113 +++++++++++++++++++++ pkg/domain/infra/abi/terminal/terminal_linux.go | 110 -------------------- .../infra/abi/terminal/terminal_unsupported.go | 4 +- 5 files changed, 178 insertions(+), 172 deletions(-) create mode 100644 pkg/domain/infra/abi/terminal/sigproxy_commn.go delete mode 100644 pkg/domain/infra/abi/terminal/sigproxy_linux.go create mode 100644 pkg/domain/infra/abi/terminal/terminal_common.go delete mode 100644 pkg/domain/infra/abi/terminal/terminal_linux.go (limited to 'pkg') diff --git a/pkg/domain/infra/abi/terminal/sigproxy_commn.go b/pkg/domain/infra/abi/terminal/sigproxy_commn.go new file mode 100644 index 000000000..3a0132ef3 --- /dev/null +++ b/pkg/domain/infra/abi/terminal/sigproxy_commn.go @@ -0,0 +1,63 @@ +//go:build linux || freebsd +// +build linux freebsd + +package terminal + +import ( + "errors" + "os" + "syscall" + + "github.com/containers/podman/v4/libpod" + "github.com/containers/podman/v4/libpod/define" + "github.com/containers/podman/v4/libpod/shutdown" + "github.com/containers/podman/v4/pkg/signal" + "github.com/sirupsen/logrus" +) + +// Make sure the signal buffer is sufficiently big. +// runc is using the same value. +const signalBufferSize = 2048 + +// ProxySignals ... +func ProxySignals(ctr *libpod.Container) { + // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going + // to the container now. + shutdown.Stop() //nolint: errcheck + + sigBuffer := make(chan os.Signal, signalBufferSize) + signal.CatchAll(sigBuffer) + + logrus.Debugf("Enabling signal proxying") + + go func() { + for s := range sigBuffer { + // Ignore SIGCHLD and SIGPIPE - these are mostly likely + // intended for the podman command itself. + // SIGURG was added because of golang 1.14 and its preemptive changes + // causing more signals to "show up". + // https://github.com/containers/podman/issues/5483 + if s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG { + continue + } + + if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil { + if errors.Is(err, define.ErrCtrStateInvalid) { + logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID()) + } else { + logrus.Errorf("forwarding signal %d to container %s: %v", s, ctr.ID(), err) + } + // If the container dies, and we find out here, + // we need to forward that one signal to + // ourselves so that it is not lost, and then + // we terminate the proxy and let the defaults + // play out. + signal.StopCatch(sigBuffer) + if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil { + logrus.Errorf("Failed to kill pid %d", syscall.Getpid()) + } + return + } + } + }() +} diff --git a/pkg/domain/infra/abi/terminal/sigproxy_linux.go b/pkg/domain/infra/abi/terminal/sigproxy_linux.go deleted file mode 100644 index 16d345f06..000000000 --- a/pkg/domain/infra/abi/terminal/sigproxy_linux.go +++ /dev/null @@ -1,60 +0,0 @@ -package terminal - -import ( - "errors" - "os" - "syscall" - - "github.com/containers/podman/v4/libpod" - "github.com/containers/podman/v4/libpod/define" - "github.com/containers/podman/v4/libpod/shutdown" - "github.com/containers/podman/v4/pkg/signal" - "github.com/sirupsen/logrus" -) - -// Make sure the signal buffer is sufficiently big. -// runc is using the same value. -const signalBufferSize = 2048 - -// ProxySignals ... -func ProxySignals(ctr *libpod.Container) { - // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going - // to the container now. - shutdown.Stop() //nolint: errcheck - - sigBuffer := make(chan os.Signal, signalBufferSize) - signal.CatchAll(sigBuffer) - - logrus.Debugf("Enabling signal proxying") - - go func() { - for s := range sigBuffer { - // Ignore SIGCHLD and SIGPIPE - these are mostly likely - // intended for the podman command itself. - // SIGURG was added because of golang 1.14 and its preemptive changes - // causing more signals to "show up". - // https://github.com/containers/podman/issues/5483 - if s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG { - continue - } - - if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil { - if errors.Is(err, define.ErrCtrStateInvalid) { - logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID()) - } else { - logrus.Errorf("forwarding signal %d to container %s: %v", s, ctr.ID(), err) - } - // If the container dies, and we find out here, - // we need to forward that one signal to - // ourselves so that it is not lost, and then - // we terminate the proxy and let the defaults - // play out. - signal.StopCatch(sigBuffer) - if err := syscall.Kill(syscall.Getpid(), s.(syscall.Signal)); err != nil { - logrus.Errorf("Failed to kill pid %d", syscall.Getpid()) - } - return - } - } - }() -} diff --git a/pkg/domain/infra/abi/terminal/terminal_common.go b/pkg/domain/infra/abi/terminal/terminal_common.go new file mode 100644 index 000000000..afae2c085 --- /dev/null +++ b/pkg/domain/infra/abi/terminal/terminal_common.go @@ -0,0 +1,113 @@ +//go:build linux || freebsd +// +build linux freebsd + +package terminal + +import ( + "bufio" + "context" + "fmt" + "os" + + "github.com/containers/common/pkg/resize" + "github.com/containers/podman/v4/libpod" + "github.com/containers/podman/v4/libpod/define" + "github.com/sirupsen/logrus" + "golang.org/x/term" +) + +// ExecAttachCtr execs and attaches to a container +func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { + var resizechan chan resize.TerminalSize + haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) + + // Check if we are attached to a terminal. If we are, generate resize + // events, and set the terminal to raw mode + if haveTerminal && execConfig.Terminal { + resizechan = make(chan resize.TerminalSize) + cancel, oldTermState, err := handleTerminalAttach(ctx, resizechan) + if err != nil { + return -1, err + } + defer cancel() + defer func() { + if err := restoreTerminal(oldTermState); err != nil { + logrus.Errorf("Unable to restore terminal: %q", err) + } + }() + } + return ctr.Exec(execConfig, streams, resizechan) +} + +// StartAttachCtr starts and (if required) attaches to a container +// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream +// error. we may need to just lint disable this one. +func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer + resize := make(chan resize.TerminalSize) + + haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) + + // Check if we are attached to a terminal. If we are, generate resize + // events, and set the terminal to raw mode + if haveTerminal && ctr.Spec().Process.Terminal { + cancel, oldTermState, err := handleTerminalAttach(ctx, resize) + if err != nil { + return err + } + defer func() { + if err := restoreTerminal(oldTermState); err != nil { + logrus.Errorf("Unable to restore terminal: %q", err) + } + }() + defer cancel() + } + + streams := new(define.AttachStreams) + streams.OutputStream = stdout + streams.ErrorStream = stderr + streams.InputStream = bufio.NewReader(stdin) + streams.AttachOutput = true + streams.AttachError = true + streams.AttachInput = true + + if stdout == nil { + logrus.Debugf("Not attaching to stdout") + streams.AttachOutput = false + } + if stderr == nil { + logrus.Debugf("Not attaching to stderr") + streams.AttachError = false + } + if stdin == nil { + logrus.Debugf("Not attaching to stdin") + streams.AttachInput = false + } + + if !startContainer { + if sigProxy { + ProxySignals(ctr) + } + + return ctr.Attach(streams, detachKeys, resize) + } + + attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, true) + if err != nil { + return err + } + + if sigProxy { + ProxySignals(ctr) + } + + if stdout == nil && stderr == nil { + fmt.Printf("%s\n", ctr.ID()) + } + + err = <-attachChan + if err != nil { + return fmt.Errorf("error attaching to container %s: %w", ctr.ID(), err) + } + + return nil +} diff --git a/pkg/domain/infra/abi/terminal/terminal_linux.go b/pkg/domain/infra/abi/terminal/terminal_linux.go deleted file mode 100644 index 222590871..000000000 --- a/pkg/domain/infra/abi/terminal/terminal_linux.go +++ /dev/null @@ -1,110 +0,0 @@ -package terminal - -import ( - "bufio" - "context" - "fmt" - "os" - - "github.com/containers/common/pkg/resize" - "github.com/containers/podman/v4/libpod" - "github.com/containers/podman/v4/libpod/define" - "github.com/sirupsen/logrus" - "golang.org/x/term" -) - -// ExecAttachCtr execs and attaches to a container -func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) { - var resizechan chan resize.TerminalSize - haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) - - // Check if we are attached to a terminal. If we are, generate resize - // events, and set the terminal to raw mode - if haveTerminal && execConfig.Terminal { - resizechan = make(chan resize.TerminalSize) - cancel, oldTermState, err := handleTerminalAttach(ctx, resizechan) - if err != nil { - return -1, err - } - defer cancel() - defer func() { - if err := restoreTerminal(oldTermState); err != nil { - logrus.Errorf("Unable to restore terminal: %q", err) - } - }() - } - return ctr.Exec(execConfig, streams, resizechan) -} - -// StartAttachCtr starts and (if required) attaches to a container -// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream -// error. we may need to just lint disable this one. -func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer - resize := make(chan resize.TerminalSize) - - haveTerminal := term.IsTerminal(int(os.Stdin.Fd())) - - // Check if we are attached to a terminal. If we are, generate resize - // events, and set the terminal to raw mode - if haveTerminal && ctr.Spec().Process.Terminal { - cancel, oldTermState, err := handleTerminalAttach(ctx, resize) - if err != nil { - return err - } - defer func() { - if err := restoreTerminal(oldTermState); err != nil { - logrus.Errorf("Unable to restore terminal: %q", err) - } - }() - defer cancel() - } - - streams := new(define.AttachStreams) - streams.OutputStream = stdout - streams.ErrorStream = stderr - streams.InputStream = bufio.NewReader(stdin) - streams.AttachOutput = true - streams.AttachError = true - streams.AttachInput = true - - if stdout == nil { - logrus.Debugf("Not attaching to stdout") - streams.AttachOutput = false - } - if stderr == nil { - logrus.Debugf("Not attaching to stderr") - streams.AttachError = false - } - if stdin == nil { - logrus.Debugf("Not attaching to stdin") - streams.AttachInput = false - } - - if !startContainer { - if sigProxy { - ProxySignals(ctr) - } - - return ctr.Attach(streams, detachKeys, resize) - } - - attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, true) - if err != nil { - return err - } - - if sigProxy { - ProxySignals(ctr) - } - - if stdout == nil && stderr == nil { - fmt.Printf("%s\n", ctr.ID()) - } - - err = <-attachChan - if err != nil { - return fmt.Errorf("error attaching to container %s: %w", ctr.ID(), err) - } - - return nil -} diff --git a/pkg/domain/infra/abi/terminal/terminal_unsupported.go b/pkg/domain/infra/abi/terminal/terminal_unsupported.go index 8fe325736..21ed6c8d4 100644 --- a/pkg/domain/infra/abi/terminal/terminal_unsupported.go +++ b/pkg/domain/infra/abi/terminal/terminal_unsupported.go @@ -1,5 +1,5 @@ -//go:build !linux -// +build !linux +//go:build !linux && !freebsd +// +build !linux,!freebsd package terminal -- cgit v1.2.3-54-g00ecf