Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
Merge pull request #526 from lifupan/stopfix
Browse files Browse the repository at this point in the history
agent: send SIGKILL instead of SIGTERM to container init process
  • Loading branch information
teawater authored Apr 11, 2019
2 parents aa37186 + 7fbd860 commit c624f63
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
44 changes: 44 additions & 0 deletions grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package main

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -919,6 +920,16 @@ func (a *agentGRPC) SignalProcess(ctx context.Context, req *pb.SignalProcessRequ
if req.ExecId == "" || status == libcontainer.Paused {
return emptyResp, ctr.container.Signal(signal, true)
} else if ctr.initProcess.id == req.ExecId {
pid, err := ctr.initProcess.process.Pid()
if err != nil {
return emptyResp, err
}
// For container initProcess, if it hasn't installed handler for "SIGTERM" signal,
// it will ignore the "SIGTERM" signal sent to it, thus send it "SIGKILL" signal
// instead of "SIGTERM" to terminate it.
if signal == syscall.SIGTERM && !isSignalHandled(pid, syscall.SIGTERM) {
signal = syscall.SIGKILL
}
return emptyResp, ctr.container.Signal(signal, false)
}

Expand All @@ -934,6 +945,39 @@ func (a *agentGRPC) SignalProcess(ctx context.Context, req *pb.SignalProcessRequ
return emptyResp, nil
}

// Check is the container process installed the
// handler for specific signal.
func isSignalHandled(pid int, signum syscall.Signal) bool {
var sigMask uint64 = 1 << (uint(signum) - 1)
procFile := fmt.Sprintf("/proc/%d/status", pid)
file, err := os.Open(procFile)
if err != nil {
agentLog.WithField("procFile", procFile).Warn("Open proc file failed")
return false
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "SigCgt:") {
maskSlice := strings.Split(line, ":")
if len(maskSlice) != 2 {
agentLog.WithField("procFile", procFile).Warn("Parse the SigCgt field failed")
return false
}
sigCgtStr := strings.TrimSpace(maskSlice[1])
sigCgtMask, err := strconv.ParseUint(sigCgtStr, 16, 64)
if err != nil {
agentLog.WithField("sigCgt", sigCgtStr).Warn("parse the SigCgt to hex failed")
return false
}
return (sigCgtMask & sigMask) == sigMask
}
}
return false
}

func (a *agentGRPC) WaitProcess(ctx context.Context, req *pb.WaitProcessRequest) (*pb.WaitProcessResponse, error) {
proc, ctr, err := a.sandbox.getProcess(req.ContainerId, req.ExecId)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"reflect"
"sort"
"strconv"
"syscall"
"testing"
"time"

Expand Down Expand Up @@ -961,3 +962,23 @@ func TestCopyFile(t *testing.T) {
// check file's content
assert.Equal(content, append(part1, part2...))
}

func TestIsSignalHandled(t *testing.T) {
assert := assert.New(t)
pid := 1

// process will not handle SIGKILL signal
signum := syscall.SIGKILL
handled := isSignalHandled(pid, signum)
assert.False(handled)

// init process will not handle SIGTERM signal
signum = syscall.SIGTERM
handled = isSignalHandled(pid, signum)
assert.False(handled)

// init process will handle the SIGQUIT signal
signum = syscall.SIGQUIT
handled = isSignalHandled(pid, signum)
assert.True(handled)
}

0 comments on commit c624f63

Please sign in to comment.