server: honor container stop timeout from CRI

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-05-15 15:27:03 +02:00
parent 20e9aeb16f
commit b3683ab184
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
6 changed files with 29 additions and 21 deletions

View file

@ -148,7 +148,7 @@ var stopContainerCommand = cli.Command{
defer conn.Close() defer conn.Close()
client := pb.NewRuntimeServiceClient(conn) client := pb.NewRuntimeServiceClient(conn)
err = StopContainer(client, context.String("id")) err = StopContainer(client, context.String("id"), -1)
if err != nil { if err != nil {
return fmt.Errorf("Stopping the container failed: %v", err) 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 // StopContainer sends a StopContainerRequest to the server, and parses
// the returned StopContainerResponse. // the returned StopContainerResponse.
func StopContainer(client pb.RuntimeServiceClient, ID string) error { func StopContainer(client pb.RuntimeServiceClient, ID string, timeout int64) error {
if ID == "" { if ID == "" {
return fmt.Errorf("ID cannot be empty") return fmt.Errorf("ID cannot be empty")
} }
_, err := client.StopContainer(context.Background(), &pb.StopContainerRequest{ _, err := client.StopContainer(context.Background(), &pb.StopContainerRequest{
ContainerId: ID, ContainerId: ID,
Timeout: timeout,
}) })
if err != nil { if err != nil {
return err return err

View file

@ -435,29 +435,36 @@ func (r *Runtime) ExecSync(c *Container, command []string, timeout int64) (resp
}, nil }, nil
} }
// StopContainer stops a container. // StopContainer stops a container. Timeout is given in seconds.
func (r *Runtime) StopContainer(c *Container) error { func (r *Runtime) StopContainer(c *Container, timeout int64) error {
c.opLock.Lock() c.opLock.Lock()
defer c.opLock.Unlock() defer c.opLock.Unlock()
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.Path(c), "kill", c.name, "TERM"); err != nil { if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.Path(c), "kill", c.name, "TERM"); err != nil {
return err return err
} }
i := 0 if timeout == -1 {
// default 10 seconds delay
timeout = 10
}
done := make(chan struct{})
go func() {
for { for {
if i == 1000 { // Check if the process is still around
err := unix.Kill(c.state.Pid, 0)
if err == syscall.ESRCH {
close(done)
break
}
}
}()
select {
case <-done:
return nil
case <-time.After(time.Duration(timeout) * time.Second):
err := unix.Kill(c.state.Pid, syscall.SIGKILL) err := unix.Kill(c.state.Pid, syscall.SIGKILL)
if err != nil && err != syscall.ESRCH { if err != nil && err != syscall.ESRCH {
return fmt.Errorf("failed to kill process: %v", err) return fmt.Errorf("failed to kill process: %v", err)
} }
break
}
// Check if the process is still around
err := unix.Kill(c.state.Pid, 0)
if err == syscall.ESRCH {
break
}
time.Sleep(10 * time.Millisecond)
i++
} }
return nil return nil

View file

@ -24,7 +24,7 @@ func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerReq
cState := s.runtime.ContainerStatus(c) cState := s.runtime.ContainerStatus(c)
if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning { 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) return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err)
} }
} }

View file

@ -22,7 +22,7 @@ func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest
} }
cStatus := s.runtime.ContainerStatus(c) cStatus := s.runtime.ContainerStatus(c)
if cStatus.Status != oci.ContainerStateStopped { 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) return nil, fmt.Errorf("failed to stop container %s: %v", c.ID(), err)
} }
} }

View file

@ -38,7 +38,7 @@ func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxR
cState := s.runtime.ContainerStatus(c) cState := s.runtime.ContainerStatus(c)
if cState.Status == oci.ContainerStateCreated || cState.Status == oci.ContainerStateRunning { 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 // Assume container is already stopped
logrus.Warnf("failed to stop container %s: %v", c.Name(), err) logrus.Warnf("failed to stop container %s: %v", c.Name(), err)
} }

View file

@ -48,7 +48,7 @@ func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxReque
} }
cStatus := s.runtime.ContainerStatus(c) cStatus := s.runtime.ContainerStatus(c)
if cStatus.Status != oci.ContainerStateStopped { 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) return nil, fmt.Errorf("failed to stop container %s in pod sandbox %s: %v", c.Name(), sb.id, err)
} }
} }