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

Commit 7fbd860

Browse files
committed
agent: send SIGKILL instead of SIGTERM to container init process
If container initProcess doesn't install any handler for SIGTERM, it will ignore this signal, thus send it SIGKILL instead of SIGTERM to terminate it. Fixes:#525 Signed-off-by: lifupan <lifupan@gmail.com>
1 parent 74639b7 commit 7fbd860

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

grpc.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package main
88

99
import (
10+
"bufio"
1011
"bytes"
1112
"encoding/json"
1213
"fmt"
@@ -919,6 +920,16 @@ func (a *agentGRPC) SignalProcess(ctx context.Context, req *pb.SignalProcessRequ
919920
if req.ExecId == "" || status == libcontainer.Paused {
920921
return emptyResp, ctr.container.Signal(signal, true)
921922
} else if ctr.initProcess.id == req.ExecId {
923+
pid, err := ctr.initProcess.process.Pid()
924+
if err != nil {
925+
return emptyResp, err
926+
}
927+
// For container initProcess, if it hasn't installed handler for "SIGTERM" signal,
928+
// it will ignore the "SIGTERM" signal sent to it, thus send it "SIGKILL" signal
929+
// instead of "SIGTERM" to terminate it.
930+
if signal == syscall.SIGTERM && !isSignalHandled(pid, syscall.SIGTERM) {
931+
signal = syscall.SIGKILL
932+
}
922933
return emptyResp, ctr.container.Signal(signal, false)
923934
}
924935

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

948+
// Check is the container process installed the
949+
// handler for specific signal.
950+
func isSignalHandled(pid int, signum syscall.Signal) bool {
951+
var sigMask uint64 = 1 << (uint(signum) - 1)
952+
procFile := fmt.Sprintf("/proc/%d/status", pid)
953+
file, err := os.Open(procFile)
954+
if err != nil {
955+
agentLog.WithField("procFile", procFile).Warn("Open proc file failed")
956+
return false
957+
}
958+
defer file.Close()
959+
960+
scanner := bufio.NewScanner(file)
961+
for scanner.Scan() {
962+
line := scanner.Text()
963+
if strings.HasPrefix(line, "SigCgt:") {
964+
maskSlice := strings.Split(line, ":")
965+
if len(maskSlice) != 2 {
966+
agentLog.WithField("procFile", procFile).Warn("Parse the SigCgt field failed")
967+
return false
968+
}
969+
sigCgtStr := strings.TrimSpace(maskSlice[1])
970+
sigCgtMask, err := strconv.ParseUint(sigCgtStr, 16, 64)
971+
if err != nil {
972+
agentLog.WithField("sigCgt", sigCgtStr).Warn("parse the SigCgt to hex failed")
973+
return false
974+
}
975+
return (sigCgtMask & sigMask) == sigMask
976+
}
977+
}
978+
return false
979+
}
980+
937981
func (a *agentGRPC) WaitProcess(ctx context.Context, req *pb.WaitProcessRequest) (*pb.WaitProcessResponse, error) {
938982
proc, ctr, err := a.sandbox.getProcess(req.ContainerId, req.ExecId)
939983
if err != nil {

grpc_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"reflect"
1616
"sort"
1717
"strconv"
18+
"syscall"
1819
"testing"
1920
"time"
2021

@@ -961,3 +962,23 @@ func TestCopyFile(t *testing.T) {
961962
// check file's content
962963
assert.Equal(content, append(part1, part2...))
963964
}
965+
966+
func TestIsSignalHandled(t *testing.T) {
967+
assert := assert.New(t)
968+
pid := 1
969+
970+
// process will not handle SIGKILL signal
971+
signum := syscall.SIGKILL
972+
handled := isSignalHandled(pid, signum)
973+
assert.False(handled)
974+
975+
// init process will not handle SIGTERM signal
976+
signum = syscall.SIGTERM
977+
handled = isSignalHandled(pid, signum)
978+
assert.False(handled)
979+
980+
// init process will handle the SIGQUIT signal
981+
signum = syscall.SIGQUIT
982+
handled = isSignalHandled(pid, signum)
983+
assert.True(handled)
984+
}

0 commit comments

Comments
 (0)