Browse Source

daemon: close exec config streams with timeout

Closing streams of exec config can be blocked idefinitely when
writes of output streams are blocked - similarly to what may
happen to container's own output streams when there is a
non-reading attached client. This may block container shutdown,
preventing it from completing. Use context with timeout to limit
the time waiting for execConfig.CloseStreams to complete during
container shutdown.

Signed-off-by: Daniil Sigalov <asterite@seclab.cs.msu.ru>
Daniil Sigalov 4 years ago
parent
commit
695ebbafd8
3 changed files with 6 additions and 4 deletions
  1. 2 2
      container/exec.go
  2. 1 1
      daemon/exec.go
  3. 3 1
      daemon/monitor.go

+ 2 - 2
container/exec.go

@@ -65,8 +65,8 @@ func (c *ExecConfig) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
 }
 
 // CloseStreams closes the stdio streams for the exec
-func (c *ExecConfig) CloseStreams() error {
-	return c.StreamConfig.CloseStreams(context.Background())
+func (c *ExecConfig) CloseStreams(ctx context.Context) error {
+	return c.StreamConfig.CloseStreams(ctx)
 }
 
 // SetExitCode sets the exec config's exit code

+ 1 - 1
daemon/exec.go

@@ -187,7 +187,7 @@ func (daemon *Daemon) ContainerExecStart(ctx context.Context, name string, optio
 			ec.Running = false
 			exitCode := 126
 			ec.ExitCode = &exitCode
-			if err := ec.CloseStreams(); err != nil {
+			if err := ec.CloseStreams(ctx); err != nil {
 				log.G(ctx).Errorf("failed to cleanup exec %s streams: %s", ec.Container.ID, err)
 			}
 			ec.Unlock()

+ 3 - 1
daemon/monitor.go

@@ -191,9 +191,11 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerdtypes.EventType, ei
 			execConfig.StreamConfig.Wait(ctx)
 			cancel()
 
-			if err := execConfig.CloseStreams(); err != nil {
+			ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
+			if err := execConfig.CloseStreams(ctx); err != nil {
 				log.G(ctx).Errorf("failed to cleanup exec %s streams: %s", c.ID, err)
 			}
+			cancel()
 
 			exitCode = ec