From dc6f5ef3b98c71ff8da3ed39193c5745eb9329e1 Mon Sep 17 00:00:00 2001 From: Shiming Zhang Date: Mon, 8 Feb 2021 17:35:30 +0800 Subject: [PATCH] Fix repeated sending signal Signed-off-by: Shiming Zhang --- pkg/cri/server/container_stop.go | 20 +++++++++++++++++--- pkg/cri/store/container/container.go | 8 ++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pkg/cri/server/container_stop.go b/pkg/cri/server/container_stop.go index c584a535b..56b10756c 100644 --- a/pkg/cri/server/container_stop.go +++ b/pkg/cri/server/container_stop.go @@ -17,6 +17,7 @@ package server import ( + "sync/atomic" "syscall" "time" @@ -129,9 +130,22 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore if err != nil { return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal) } - log.G(ctx).Infof("Stop container %q with signal %v", id, sig) - if err = task.Kill(ctx, sig); err != nil && !errdefs.IsNotFound(err) { - return errors.Wrapf(err, "failed to stop container %q", id) + + var sswt bool + if container.IsStopSignaledWithTimeout == nil { + log.G(ctx).Infof("unable to ensure stop signal %v was not sent twice to container %v", sig, id) + sswt = true + } else { + sswt = atomic.CompareAndSwapUint32(container.IsStopSignaledWithTimeout, 0, 1) + } + + if sswt { + log.G(ctx).Infof("Stop container %q with signal %v", id, sig) + if err = task.Kill(ctx, sig); err != nil && !errdefs.IsNotFound(err) { + return errors.Wrapf(err, "failed to stop container %q", id) + } + } else { + log.G(ctx).Infof("Skipping the sending of signal %v to container %q because a prior stop with timeout>0 request already sent the signal", sig, id) } sigTermCtx, sigTermCtxCancel := context.WithTimeout(ctx, timeout) diff --git a/pkg/cri/store/container/container.go b/pkg/cri/store/container/container.go index 11cc523b7..c74965b7a 100644 --- a/pkg/cri/store/container/container.go +++ b/pkg/cri/store/container/container.go @@ -42,6 +42,9 @@ type Container struct { IO *cio.ContainerIO // StopCh is used to propagate the stop information of the container. *store.StopCh + // IsStopSignaledWithTimeout the default is 0, and it is set to 1 after sending + // the signal once to avoid repeated sending of the signal. + IsStopSignaledWithTimeout *uint32 } // Opts sets specific information to newly created Container. @@ -81,8 +84,9 @@ func WithStatus(status Status, root string) Opts { // NewContainer creates an internally used container type. func NewContainer(metadata Metadata, opts ...Opts) (Container, error) { c := Container{ - Metadata: metadata, - StopCh: store.NewStopCh(), + Metadata: metadata, + StopCh: store.NewStopCh(), + IsStopSignaledWithTimeout: new(uint32), } for _, o := range opts { if err := o(&c); err != nil {