github.com/georgethebeatle/containerd@v0.2.5/supervisor/exit.go (about) 1 package supervisor 2 3 import ( 4 "time" 5 6 "github.com/Sirupsen/logrus" 7 "github.com/docker/containerd/runtime" 8 ) 9 10 // ExitTask holds needed parameters to execute the exit task 11 type ExitTask struct { 12 baseTask 13 Process runtime.Process 14 } 15 16 func (s *Supervisor) exit(t *ExitTask) error { 17 start := time.Now() 18 proc := t.Process 19 status, err := proc.ExitStatus() 20 if err != nil { 21 logrus.WithFields(logrus.Fields{ 22 "error": err, 23 "pid": proc.ID(), 24 "id": proc.Container().ID(), 25 "systemPid": proc.SystemPid(), 26 }).Error("containerd: get exit status") 27 } 28 logrus.WithFields(logrus.Fields{ 29 "pid": proc.ID(), 30 "status": status, 31 "id": proc.Container().ID(), 32 "systemPid": proc.SystemPid(), 33 }).Debug("containerd: process exited") 34 35 // if the process is the the init process of the container then 36 // fire a separate event for this process 37 if proc.ID() != runtime.InitProcessID { 38 ne := &ExecExitTask{ 39 ID: proc.Container().ID(), 40 PID: proc.ID(), 41 Status: status, 42 Process: proc, 43 } 44 s.execExit(ne) 45 return nil 46 } 47 container := proc.Container() 48 ne := &DeleteTask{ 49 ID: container.ID(), 50 Status: status, 51 PID: proc.ID(), 52 Process: proc, 53 } 54 s.delete(ne) 55 56 ExitProcessTimer.UpdateSince(start) 57 58 return nil 59 } 60 61 // ExecExitTask holds needed parameters to execute the exec exit task 62 type ExecExitTask struct { 63 baseTask 64 ID string 65 PID string 66 Status uint32 67 Process runtime.Process 68 } 69 70 func (s *Supervisor) execExit(t *ExecExitTask) error { 71 container := t.Process.Container() 72 // exec process: we remove this process without notifying the main event loop 73 if err := container.RemoveProcess(t.PID); err != nil { 74 logrus.WithField("error", err).Error("containerd: find container for pid") 75 } 76 // If the exec spawned children which are still using its IO 77 // waiting here will block until they die or close their IO 78 // descriptors. 79 // Hence, we use a go routine to avoid block all other operations 80 go func() { 81 t.Process.Wait() 82 s.notifySubscribers(Event{ 83 Timestamp: time.Now(), 84 ID: t.ID, 85 Type: StateExit, 86 PID: t.PID, 87 Status: t.Status, 88 }) 89 }() 90 return nil 91 }