Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / containerd / containerd / supervisor / exit.go
1 package supervisor
2
3 import (
4         "time"
5
6         "github.com/Sirupsen/logrus"
7         "github.com/containerd/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         synCh := s.getExecSyncChannel(t.ID, t.PID)
77         // If the exec spawned children which are still using its IO
78         // waiting here will block until they die or close their IO
79         // descriptors.
80         // Hence, we use a go routine to avoid blocking all other operations
81         go func() {
82                 t.Process.Wait()
83                 s.notifySubscribers(Event{
84                         Timestamp: time.Now(),
85                         ID:        t.ID,
86                         Type:      StateExit,
87                         PID:       t.PID,
88                         Status:    t.Status,
89                 })
90                 close(synCh)
91         }()
92         return nil
93 }