attach: set the terminal size and handle SIGWINCH

Notify conmon when the terminal size changes.  Use the same notification
to set the correct initial size.

Closes: https://github.com/projectatomic/libpod/issues/351

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>

Closes: #448
Approved by: baude
This commit is contained in:
Giuseppe Scrivano
2018-03-04 14:19:46 +01:00
committed by Atomic Bot
parent 5ca69aaa41
commit bbf9a313c3
2 changed files with 42 additions and 11 deletions

View File

@ -4,17 +4,20 @@ import (
"encoding/json"
"io/ioutil"
"os"
gosignal "os/signal"
"path/filepath"
"strconv"
"time"
"github.com/docker/docker/daemon/caps"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/term"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod/driver"
"github.com/projectatomic/libpod/pkg/inspect"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/remotecommand"
)
@ -345,6 +348,31 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
return waitErr
}
func resizeTty(resize chan remotecommand.TerminalSize) {
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, signal.SIGWINCH)
sendUpdate := func() {
winsize, err := term.GetWinsize(os.Stdin.Fd())
if err != nil {
logrus.Warnf("Could not get terminal size %v", err)
return
}
resize <- remotecommand.TerminalSize{
Width: winsize.Width,
Height: winsize.Height,
}
}
go func() {
defer close(resize)
// Update the terminal size immediately without waiting
// for a SIGWINCH to get the correct initial size.
sendUpdate()
for range sigchan {
sendUpdate()
}
}()
}
// Attach attaches to a container
// Returns fully qualified URL of streaming server for the container
func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error {
@ -373,8 +401,11 @@ func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) erro
}
resize := make(chan remotecommand.TerminalSize)
if terminal.IsTerminal(int(os.Stdin.Fd())) {
resizeTty(resize)
} else {
defer close(resize)
}
err = c.attachContainerSocket(resize, noStdin, detachKeys, attached)
return err
}

View File

@ -56,17 +56,17 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
term.SetRawTerminal(inputStream.Fd())
}
kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
controlPath := filepath.Join(c.bundlePath(), "ctl")
controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0)
if err != nil {
return errors.Wrapf(err, "failed to open container ctl file")
logrus.Debugf("Could not open ctl file: %v", err)
return
}
defer controlFile.Close()
kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) {
logrus.Debugf("Received a resize event: %+v", size)
_, err := fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width)
if err != nil {
if _, err = fmt.Fprintf(controlFile, "%d %d %d\n", 1, size.Height, size.Width); err != nil {
logrus.Warnf("Failed to write to control file to resize terminal: %v", err)
}
})