Skip to content

Commit

Permalink
Force Attach() to send a SIGWINCH and redraw
Browse files Browse the repository at this point in the history
Basically, we want to force the application in the container to
(iff the container was made with a terminal) redraw said terminal
immediately after an attach completes, so the fresh Attach
session will be able to see what's going on (e.g. will have a
shell prompt). Our current attach functions are unfortunately
geared more towards `podman run` than `podman attach` and will
start forwarding resize events *immediately* instead of waiting
until the attach session is alive (much safer for short-lived
`podman run` sessions, but broken for the `podman attach` case).
To avoid a major rewrite, let's just manually send a SIGWINCH
after attach succeeds to force a redraw.

Fixes containers#6253

Signed-off-by: Matthew Heon <[email protected]>
  • Loading branch information
mheon committed Sep 10, 2020
1 parent 1184cdf commit 4c155d3
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
20 changes: 18 additions & 2 deletions libpod/container_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/pkg/signal"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -129,7 +130,7 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachSt

// Attach to the container before starting it
go func() {
if err := c.attach(streams, keys, resize, true, startedChan); err != nil {
if err := c.attach(streams, keys, resize, true, startedChan, nil); err != nil {
attachChan <- err
}
close(attachChan)
Expand Down Expand Up @@ -243,8 +244,23 @@ func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-
return errors.Wrapf(define.ErrCtrStateInvalid, "can only attach to created or running containers")
}

// HACK: This is really gross, but there isn't a better way without
// splitting attach into separate versions for StartAndAttach and normal
// attaching, and I really do not want to do that right now.
// Send a SIGWINCH after attach succeeds so that most programs will
// redraw the screen for the new attach session.
attachRdy := make(chan bool)
if c.config.Spec.Process != nil && c.config.Spec.Process.Terminal {
go func() {
<-attachRdy
if err := c.ociRuntime.KillContainer(c, uint(signal.SIGWINCH), false); err != nil {
logrus.Warnf("Unable to send SIGWINCH to container %s after attach: %v", c.ID(), err)
}
}()
}

c.newContainerEvent(events.Attach)
return c.attach(streams, keys, resize, false, nil)
return c.attach(streams, keys, resize, false, nil, attachRdy)
}

// HTTPAttach forwards an attach session over a hijacked HTTP session.
Expand Down
5 changes: 4 additions & 1 deletion libpod/oci_attach_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const (
// Attach to the given container
// Does not check if state is appropriate
// started is only required if startContainer is true
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
}
Expand Down Expand Up @@ -74,6 +74,9 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
}

receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
if attachRdy != nil {
attachRdy <- true
}
return readStdio(streams, receiveStdoutError, stdinDone)
}

Expand Down
2 changes: 1 addition & 1 deletion libpod/oci_attach_unsupported.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"k8s.io/client-go/tools/remotecommand"
)

func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool) error {
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
return define.ErrNotImplemented
}

Expand Down

0 comments on commit 4c155d3

Please sign in to comment.