mirror of
https://github.com/containers/podman.git
synced 2025-07-04 10:10:32 +08:00
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>
This commit is contained in:
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containers/podman/v2/libpod/define"
|
"github.com/containers/podman/v2/libpod/define"
|
||||||
"github.com/containers/podman/v2/libpod/events"
|
"github.com/containers/podman/v2/libpod/events"
|
||||||
|
"github.com/containers/podman/v2/pkg/signal"
|
||||||
"github.com/opentracing/opentracing-go"
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"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
|
// Attach to the container before starting it
|
||||||
go func() {
|
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
|
attachChan <- err
|
||||||
}
|
}
|
||||||
close(attachChan)
|
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")
|
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)
|
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.
|
// HTTPAttach forwards an attach session over a hijacked HTTP session.
|
||||||
|
@ -31,7 +31,7 @@ const (
|
|||||||
// Attach to the given container
|
// Attach to the given container
|
||||||
// Does not check if state is appropriate
|
// Does not check if state is appropriate
|
||||||
// started is only required if startContainer is true
|
// 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 {
|
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
|
||||||
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
|
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)
|
receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
|
||||||
|
if attachRdy != nil {
|
||||||
|
attachRdy <- true
|
||||||
|
}
|
||||||
return readStdio(streams, receiveStdoutError, stdinDone)
|
return readStdio(streams, receiveStdoutError, stdinDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"k8s.io/client-go/tools/remotecommand"
|
"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
|
return define.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user