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 }