1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
From: wheat2018 <1151937289@qq.com>
Date: Tue, 13 Aug 2024 15:56:31 +0800
Subject: fix goroutine leak of container Attach
The monitor goroutine (runs (*ContainerIO).Attach.func1) of Attach will
never finish if it attaches to a container without any stdout or stderr
output. Wait for http context cancel and break the pipe actively to
address the issue.
Signed-off-by: wheat2018 <1151937289@qq.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
(cherry picked from commit a0d0f0ef68935338d2c710db164fa7820f692530)
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
---
pkg/cri/io/container_io.go | 14 +++++++++++---
pkg/cri/sbserver/container_attach.go | 2 +-
pkg/cri/server/container_attach.go | 2 +-
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/pkg/cri/io/container_io.go b/pkg/cri/io/container_io.go
index 70bc8b7..e158410 100644
--- a/pkg/cri/io/container_io.go
+++ b/pkg/cri/io/container_io.go
@@ -17,6 +17,7 @@
package io
import (
+ "context"
"errors"
"io"
"strings"
@@ -134,7 +135,7 @@ func (c *ContainerIO) Pipe() {
// Attach attaches container stdio.
// TODO(random-liu): Use pools.Copy in docker to reduce memory usage?
-func (c *ContainerIO) Attach(opts AttachOptions) {
+func (c *ContainerIO) Attach(ctx context.Context, opts AttachOptions) {
var wg sync.WaitGroup
key := util.GenerateID()
stdinKey := streamKey(c.id, "attach-"+key, Stdin)
@@ -175,8 +176,15 @@ func (c *ContainerIO) Attach(opts AttachOptions) {
}
attachStream := func(key string, close <-chan struct{}) {
- <-close
- logrus.Infof("Attach stream %q closed", key)
+ select {
+ case <-close:
+ logrus.Infof("Attach stream %q closed", key)
+ case <-ctx.Done():
+ logrus.Infof("Attach client of %q cancelled", key)
+ // Avoid writeGroup heap up
+ c.stdoutGroup.Remove(key)
+ c.stderrGroup.Remove(key)
+ }
// Make sure stdin gets closed.
if stdinStreamRC != nil {
stdinStreamRC.Close()
diff --git a/pkg/cri/sbserver/container_attach.go b/pkg/cri/sbserver/container_attach.go
index 8527071..315ac8a 100644
--- a/pkg/cri/sbserver/container_attach.go
+++ b/pkg/cri/sbserver/container_attach.go
@@ -79,6 +79,6 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re
},
}
// TODO(random-liu): Figure out whether we need to support historical output.
- cntr.IO.Attach(opts)
+ cntr.IO.Attach(ctx, opts)
return nil
}
diff --git a/pkg/cri/server/container_attach.go b/pkg/cri/server/container_attach.go
index d7d0096..465b3d8 100644
--- a/pkg/cri/server/container_attach.go
+++ b/pkg/cri/server/container_attach.go
@@ -79,6 +79,6 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re
},
}
// TODO(random-liu): Figure out whether we need to support historical output.
- cntr.IO.Attach(opts)
+ cntr.IO.Attach(ctx, opts)
return nil
}
|