aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@pm.me>2020-09-10 17:28:22 -0400
committerMatthew Heon <matthew.heon@pm.me>2020-09-10 17:54:47 -0400
commit4c155d36cba90fd07f75c6d7d6f09848b88dac4a (patch)
tree79f3534c22c26e493e9ac01e519a61cb740ca486
parent1184cdf03d8464451d36b24643e57b65a8b97980 (diff)
downloadpodman-4c155d36cba90fd07f75c6d7d6f09848b88dac4a.tar.gz
podman-4c155d36cba90fd07f75c6d7d6f09848b88dac4a.tar.bz2
podman-4c155d36cba90fd07f75c6d7d6f09848b88dac4a.zip
Force Attach() to send a SIGWINCH and redraw
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 #6253 Signed-off-by: Matthew Heon <matthew.heon@pm.me>
-rw-r--r--libpod/container_api.go20
-rw-r--r--libpod/oci_attach_linux.go5
-rw-r--r--libpod/oci_attach_unsupported.go2
3 files changed, 23 insertions, 4 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 0d7bbacd0..aef37dd59 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -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"
@@ -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)
@@ -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.
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index 622c613d9..74af449ed 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -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")
}
@@ -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)
}
diff --git a/libpod/oci_attach_unsupported.go b/libpod/oci_attach_unsupported.go
index cd7c674b2..317dfdc90 100644
--- a/libpod/oci_attach_unsupported.go
+++ b/libpod/oci_attach_unsupported.go
@@ -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
}