github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/containerd/supervisor/monitor_solaris.go (about)

     1  // +build solaris,cgo
     2  
     3  package supervisor
     4  
     5  /*
     6  #include <port.h>
     7  #include <poll.h>
     8  #include <stdio.h>
     9  #include <stdlib.h>
    10  #include <unistd.h>
    11  
    12  int portAssociate(int port, int fd) {
    13  	if (port_associate(port, PORT_SOURCE_FD, fd, POLLIN | POLLHUP, NULL) < 0) {
    14  		return 1;
    15  	}
    16  }
    17  
    18  port_event_t* getEvent(int e_fd) {
    19  	port_event_t *ev;
    20  	ev = (port_event_t *)malloc(sizeof(port_event_t));
    21  	if (port_get(e_fd, ev, NULL) < 0) {
    22  		return NULL;
    23  	}
    24  	return ev;
    25  }
    26  
    27  int getFd(uintptr_t x) {
    28  	return *(int *)x;
    29  }
    30  
    31  void freeEvent( port_event_t *ev){
    32  	free(ev);
    33  }
    34  */
    35  import "C"
    36  import (
    37  	"sync"
    38  	"unsafe"
    39  
    40  	"github.com/Sirupsen/logrus"
    41  	"github.com/docker/containerd/runtime"
    42  )
    43  
    44  // NewMonitor starts a new process monitor and returns it
    45  func NewMonitor() (*Monitor, error) {
    46  	m := &Monitor{
    47  		receivers: make(map[int]interface{}),
    48  		exits:     make(chan runtime.Process, 1024),
    49  		ooms:      make(chan string, 1024),
    50  	}
    51  	fd, err := C.port_create()
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	m.epollFd = int(fd)
    57  	go m.start()
    58  	return m, nil
    59  }
    60  
    61  // Monitor represents a runtime.Process monitor
    62  type Monitor struct {
    63  	m         sync.Mutex
    64  	receivers map[int]interface{}
    65  	exits     chan runtime.Process
    66  	ooms      chan string
    67  	epollFd   int
    68  }
    69  
    70  // Exits returns the channel used to notify of a process exit
    71  func (m *Monitor) Exits() chan runtime.Process {
    72  	return m.exits
    73  }
    74  
    75  // OOMs returns the channel used to notify of a container exit due to OOM
    76  func (m *Monitor) OOMs() chan string {
    77  	return m.ooms
    78  }
    79  
    80  // Monitor adds a process to the list of the one being monitored
    81  func (m *Monitor) Monitor(p runtime.Process) error {
    82  	m.m.Lock()
    83  	defer m.m.Unlock()
    84  	fd := p.ExitFD()
    85  	if _, err := C.port_associate(C.int(m.epollFd), C.PORT_SOURCE_FD, C.uintptr_t(fd), C.POLLIN|C.POLLHUP, unsafe.Pointer(&fd)); err != nil {
    86  		return err
    87  	}
    88  	EpollFdCounter.Inc(1)
    89  	m.receivers[fd] = p
    90  	return nil
    91  }
    92  
    93  // MonitorOOM adds a container to the list of the ones monitored for OOM
    94  // There is no OOM-Killer on Solaris therefore nothing to setup
    95  func (m *Monitor) MonitorOOM(c runtime.Container) error {
    96  	return nil
    97  }
    98  
    99  // Close cleans up resources allocated by NewMonitor()
   100  func (m *Monitor) Close() error {
   101  	_, err := C.close(C.int(m.epollFd))
   102  	return err
   103  }
   104  
   105  func (m *Monitor) start() {
   106  	for {
   107  		ev := C.getEvent(C.int(m.epollFd))
   108  		if ev == nil {
   109  			continue
   110  		}
   111  		fd := int(C.getFd(C.uintptr_t(uintptr((ev.portev_user)))))
   112  
   113  		if fd < 0 {
   114  			logrus.Warnf("containerd: epoll wait")
   115  		}
   116  
   117  		m.m.Lock()
   118  		r := m.receivers[fd]
   119  		switch t := r.(type) {
   120  		case runtime.Process:
   121  			if ev.portev_events == C.POLLHUP {
   122  				delete(m.receivers, fd)
   123  				if err := t.Close(); err != nil {
   124  					logrus.Warnf("containerd: close process IO")
   125  				}
   126  				EpollFdCounter.Dec(1)
   127  				m.exits <- t
   128  			}
   129  		case runtime.OOM:
   130  			// always flush the event fd
   131  			t.Flush()
   132  			if t.Removed() {
   133  				delete(m.receivers, fd)
   134  				// epoll will remove the fd from its set after it has been closed
   135  				t.Close()
   136  				EpollFdCounter.Dec(1)
   137  			} else {
   138  				m.ooms <- t.ContainerID()
   139  			}
   140  		}
   141  		m.m.Unlock()
   142  		C.freeEvent(ev)
   143  	}
   144  }