github.com/dims/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  }