attach: close streams when done

When Compose is watching a project/reattaching streams on container
start, it will make new API `ContainerAttach()` calls every time a
container it's watching is started. However, it only closes the stream
when the context used to start the attach is canceled.

This means that if a user has a project with multiple containers where
containers keep restarting, Compose will attach to the new containers
but never close the previous streams, causing fds to pile up and
goroutines on the engine to get stuck.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This commit is contained in:
Laura Brehm 2024-09-10 13:30:14 +01:00 коммит произвёл Guillaume Lours
Родитель b633c5c3e1
Коммит 329ad73922
1 изменённых файлов: 4 добавлений и 6 удалений

Просмотреть файл

@ -102,9 +102,7 @@ func (s *composeService) attachContainer(ctx context.Context, container moby.Con
func (s *composeService) attachContainerStreams(ctx context.Context, container string, tty bool, stdin io.ReadCloser, stdout, stderr io.WriteCloser) (func(), chan bool, error) {
detached := make(chan bool)
var (
restore = func() { /* noop */ }
)
restore := func() { /* noop */ }
if stdin != nil {
in := streams.NewIn(stdin)
if in.IsTerminal() {
@ -128,7 +126,6 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
if stdin != nil {
stdin.Close() //nolint:errcheck
}
streamOut.Close() //nolint:errcheck
}()
if streamIn != nil && stdin != nil {
@ -143,8 +140,9 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
if stdout != nil {
go func() {
defer stdout.Close() //nolint:errcheck
defer stderr.Close() //nolint:errcheck
defer stdout.Close() //nolint:errcheck
defer stderr.Close() //nolint:errcheck
defer streamOut.Close() //nolint:errcheck
if tty {
io.Copy(stdout, streamOut) //nolint:errcheck
} else {