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

Commit c624f63

Browse files
authored
Merge pull request #526 from lifupan/stopfix
agent: send SIGKILL instead of SIGTERM to container init process
2 parents aa37186 + 7fbd860 commit c624f63

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)