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()
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

View file

@ -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
if timeout == -1 {
// default 10 seconds delay
timeout = 10
}
done := make(chan struct{})
go func() {
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)
if err != nil && err != syscall.ESRCH {
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

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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)
}
}