...
1 package main
2
3 import (
4 "os"
5 "os/signal"
6
7 "github.com/opencontainers/runc/libcontainer"
8 "github.com/opencontainers/runc/libcontainer/system"
9 "github.com/opencontainers/runc/libcontainer/utils"
10
11 "github.com/sirupsen/logrus"
12 "golang.org/x/sys/unix"
13 )
14
15 const signalBufferSize = 2048
16
17
18
19
20
21 func newSignalHandler(enableSubreaper bool, notifySocket *notifySocket) *signalHandler {
22 if enableSubreaper {
23
24 if err := system.SetSubreaper(1); err != nil {
25 logrus.Warn(err)
26 }
27 }
28
29
30 s := make(chan os.Signal, signalBufferSize)
31
32 signal.Notify(s)
33 return &signalHandler{
34 signals: s,
35 notifySocket: notifySocket,
36 }
37 }
38
39
40
41 type exit struct {
42 pid int
43 status int
44 }
45
46 type signalHandler struct {
47 signals chan os.Signal
48 notifySocket *notifySocket
49 }
50
51
52
53 func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach bool) (int, error) {
54
55
56 if detach && h.notifySocket == nil {
57 return 0, nil
58 }
59
60 pid1, err := process.Pid()
61 if err != nil {
62 return -1, err
63 }
64
65 if h.notifySocket != nil {
66 if detach {
67 _ = h.notifySocket.run(pid1)
68 return 0, nil
69 }
70 _ = h.notifySocket.run(os.Getpid())
71 go func() { _ = h.notifySocket.run(0) }()
72 }
73
74
75
76 _ = tty.resize()
77
78 for s := range h.signals {
79 switch s {
80 case unix.SIGWINCH:
81
82 _ = tty.resize()
83 case unix.SIGCHLD:
84 exits, err := h.reap()
85 if err != nil {
86 logrus.Error(err)
87 }
88 for _, e := range exits {
89 logrus.WithFields(logrus.Fields{
90 "pid": e.pid,
91 "status": e.status,
92 }).Debug("process exited")
93 if e.pid == pid1 {
94
95
96
97 _, _ = process.Wait()
98 return e.status, nil
99 }
100 }
101 default:
102 logrus.Debugf("sending signal to process %s", s)
103 if err := unix.Kill(pid1, s.(unix.Signal)); err != nil {
104 logrus.Error(err)
105 }
106 }
107 }
108 return -1, nil
109 }
110
111
112
113 func (h *signalHandler) reap() (exits []exit, err error) {
114 var (
115 ws unix.WaitStatus
116 rus unix.Rusage
117 )
118 for {
119 pid, err := unix.Wait4(-1, &ws, unix.WNOHANG, &rus)
120 if err != nil {
121 if err == unix.ECHILD {
122 return exits, nil
123 }
124 return nil, err
125 }
126 if pid <= 0 {
127 return exits, nil
128 }
129 exits = append(exits, exit{
130 pid: pid,
131 status: utils.ExitStatus(ws),
132 })
133 }
134 }
135
View as plain text