@@ -28,6 +28,7 @@ import (
2828 "golang.org/x/sys/unix"
2929 runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
3030
31+ "github.com/containerd/cri/pkg/store"
3132 containerstore "github.com/containerd/cri/pkg/store/container"
3233)
3334
@@ -77,24 +78,36 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
7778 // We only need to kill the task. The event handler will Delete the
7879 // task from containerd after it handles the Exited event.
7980 if timeout > 0 {
80- stopSignal := unix .SIGTERM
81- image , err := c .imageStore .Get (container .ImageRef )
82- if err != nil {
83- // NOTE(random-liu): It's possible that the container is stopped,
84- // deleted and image is garbage collected before this point. However,
85- // the chance is really slim, even it happens, it's still fine to return
86- // an error here.
87- return errors .Wrapf (err , "failed to get image metadata %q" , container .ImageRef )
88- }
89- if image .ImageSpec .Config .StopSignal != "" {
90- stopSignal , err = signal .ParseSignal (image .ImageSpec .Config .StopSignal )
81+ stopSignal := "SIGTERM"
82+ if container .StopSignal != "" {
83+ stopSignal = container .StopSignal
84+ } else {
85+ // The image may have been deleted, and the `StopSignal` field is
86+ // just introduced to handle that.
87+ // However, for containers created before the `StopSignal` field is
88+ // introduced, still try to get the stop signal from the image config.
89+ // If the image has been deleted, logging an error and using the
90+ // default SIGTERM is still better than returning error and leaving
91+ // the container unstoppable. (See issue #990)
92+ // TODO(random-liu): Remove this logic when containerd 1.2 is deprecated.
93+ image , err := c .imageStore .Get (container .ImageRef )
9194 if err != nil {
92- return errors .Wrapf (err , "failed to parse stop signal %q" ,
93- image .ImageSpec .Config .StopSignal )
95+ if err != store .ErrNotExist {
96+ return errors .Wrapf (err , "failed to get image %q" , container .ImageRef )
97+ }
98+ logrus .Warningf ("Image %q not found, stop container with signal %q" , container .ImageRef , stopSignal )
99+ } else {
100+ if image .ImageSpec .Config .StopSignal != "" {
101+ stopSignal = image .ImageSpec .Config .StopSignal
102+ }
94103 }
95104 }
96- logrus .Infof ("Stop container %q with signal %v" , id , stopSignal )
97- if err = task .Kill (ctx , stopSignal ); err != nil && ! errdefs .IsNotFound (err ) {
105+ sig , err := signal .ParseSignal (stopSignal )
106+ if err != nil {
107+ return errors .Wrapf (err , "failed to parse stop signal %q" , stopSignal )
108+ }
109+ logrus .Infof ("Stop container %q with signal %v" , id , sig )
110+ if err = task .Kill (ctx , sig ); err != nil && ! errdefs .IsNotFound (err ) {
98111 return errors .Wrapf (err , "failed to stop container %q" , id )
99112 }
100113
0 commit comments