From b3683ab184841009e50447f8f6b469af7a5ae819 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Mon, 15 May 2017 15:27:03 +0200 Subject: [PATCH] server: honor container stop timeout from CRI Signed-off-by: Antonio Murdaca --- cmd/crioctl/container.go | 5 +++-- oci/oci.go | 37 ++++++++++++++++++++++--------------- server/container_remove.go | 2 +- server/container_stop.go | 2 +- server/sandbox_remove.go | 2 +- server/sandbox_stop.go | 2 +- 6 files changed, 29 insertions(+), 21 deletions(-) diff --git a/cmd/crioctl/container.go b/cmd/crioctl/container.go index 592e024a..693804d0 100644 --- a/cmd/crioctl/container.go +++ b/cmd/crioctl/container.go @@ -148,7 +148,7 @@ var stopContainerCommand = cli.Command{ defer conn.Close() client := pb.NewRuntimeServiceClient(conn) - err = StopContainer(client, context.String("id")) + err = StopContainer(client, context.String("id"), -1) if err != nil { return fmt.Errorf("Stopping the container failed: %v", err) } @@ -402,12 +402,13 @@ func StartContainer(client pb.RuntimeServiceClient, ID string) error { // StopContainer sends a StopContainerRequest to the server, and parses // the returned StopContainerResponse. -func StopContainer(client pb.RuntimeServiceClient, ID string) error { +func StopContainer(client pb.RuntimeServiceClient, ID string, timeout int64) error { if ID == "" { return fmt.Errorf("ID cannot be empty") } _, err := client.StopContainer(context.Background(), &pb.StopContainerRequest{ ContainerId: ID, + Timeout: timeout, }) if err != nil { return err diff --git a/oci/oci.go b/oci/oci.go index e486394a..548a941b 100644 --- a/oci/oci.go +++ b/oci/oci.go @@ -435,29 +435,36 @@ func (r *Runtime) ExecSync(c *Container, command []string, timeout int64) (resp }, nil } -// StopContainer stops a container. -func (r *Runtime) StopContainer(c *Container) error { +// StopContainer stops a container. Timeout is given in seconds. +func (r *Runtime) StopContainer(c *Container, timeout int64) error { c.opLock.Lock() defer c.opLock.Unlock() if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.Path(c), "kill", c.name, "TERM"); err != nil { return err } - i := 0 - for { - if i == 1000 { - err := unix.Kill(c.state.Pid, syscall.SIGKILL) - if err != nil && err != syscall.ESRCH { - return fmt.Errorf("failed to kill process: %v", err) + if timeout == -1 { + // default 10 seconds delay + timeout = 10 + } + done := make(chan struct{}) + go func() { + for { + // Check if the process is still around + err := unix.Kill(c.state.Pid, 0) + if err == syscall.ESRCH { + close(done) + break } - break } - // Check if the process is still around - err := unix.Kill(c.state.Pid, 0) - if err == syscall.ESRCH { - break + }() + select { + case <-done: + return nil + case <-time.After(time.Duration(timeout) * time.Second): + err := unix.Kill(c.state.Pid, syscall.SIGKILL) + if err != nil && err != syscall.ESRCH { + return fmt.Errorf("failed to kill process: %v", err) } - time.Sleep(10 * time.Millisecond) - i++ } return nil diff --git a/server/container_remove.go b/server/container_remove.go index 028ffed8..125bf246 100644 --- a/server/container_remove.go +++ b/server/container_remove.go @@ -24,7 +24,7 @@ func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerReq cState := s.runtime.ContainerStatus(c) if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning { - if err := s.runtime.StopContainer(c); err != nil { + if err := s.runtime.StopContainer(c, -1); err != nil { return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err) } } diff --git a/server/container_stop.go b/server/container_stop.go index 58865edf..6503b3fa 100644 --- a/server/container_stop.go +++ b/server/container_stop.go @@ -22,7 +22,7 @@ func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest } cStatus := s.runtime.ContainerStatus(c) if cStatus.Status != oci.ContainerStateStopped { - if err := s.runtime.StopContainer(c); err != nil { + if err := s.runtime.StopContainer(c, req.Timeout); err != nil { return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err) } } diff --git a/server/sandbox_remove.go b/server/sandbox_remove.go index 9628c6b5..e2502cba 100644 --- a/server/sandbox_remove.go +++ b/server/sandbox_remove.go @@ -38,7 +38,7 @@ func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxR cState := s.runtime.ContainerStatus(c) if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning { - if err := s.runtime.StopContainer(c); err != nil { + if err := s.runtime.StopContainer(c, -1); err != nil { // Assume container is already stopped logrus.Warnf("failed to stop container %s: %v", c.Name(), err) } diff --git a/server/sandbox_stop.go b/server/sandbox_stop.go index a6f8d32b..76a0cadf 100644 --- a/server/sandbox_stop.go +++ b/server/sandbox_stop.go @@ -48,7 +48,7 @@ func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxReque } cStatus := s.runtime.ContainerStatus(c) if cStatus.Status != oci.ContainerStateStopped { - if err := s.runtime.StopContainer(c); err != nil { + if err := s.runtime.StopContainer(c, -1); err != nil { return nil, fmt.Errorf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.id, err) } }