High level interface for low level file descriptor polling
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

epoll_linux.go 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // +build linux
  2. package poll
  3. import (
  4. "log"
  5. "strings"
  6. "sync"
  7. "golang.org/x/sys/unix"
  8. )
  9. const (
  10. maxWaitEventsBegin = 1024
  11. maxWaitEventsStop = 32768
  12. )
  13. const (
  14. EPOLLIN = unix.EPOLLIN
  15. EPOLLOUT = unix.EPOLLOUT
  16. EPOLLRDHUP = unix.EPOLLRDHUP
  17. EPOLLPRI = unix.EPOLLPRI
  18. EPOLLERR = unix.EPOLLERR
  19. EPOLLHUP = unix.EPOLLHUP
  20. EPOLLET = unix.EPOLLET
  21. EPOLLONESHOT = unix.EPOLLONESHOT
  22. EPOLLCLOSED = 0X20
  23. )
  24. // epollEvent is an epoll events configuration mask
  25. type epollEvent uint32
  26. var epollEventNames = map[epollEvent]string{
  27. EPOLLIN: "EPOLLIN",
  28. EPOLLOUT: "EPOLLOUT",
  29. EPOLLRDHUP: "EPOLLRDHUP",
  30. EPOLLPRI: "EPOLLPRI",
  31. EPOLLERR: "EPOLLERR",
  32. EPOLLHUP: "EPOLLHUP",
  33. EPOLLET: "EPOLLET",
  34. EPOLLONESHOT: "EPOLLONESHOT",
  35. EPOLLCLOSED: "EPOLLCLOSED",
  36. }
  37. func (event epollEvent) String() string {
  38. var s []string
  39. for _, mask := range []epollEvent{
  40. EPOLLIN,
  41. EPOLLOUT,
  42. EPOLLRDHUP,
  43. EPOLLPRI,
  44. EPOLLERR,
  45. EPOLLHUP,
  46. EPOLLET,
  47. EPOLLONESHOT,
  48. EPOLLCLOSED,
  49. } {
  50. if event&mask == mask {
  51. s = append(s, epollEventNames[mask])
  52. }
  53. }
  54. return strings.Join(s, "|")
  55. }
  56. func (event Event) toEpollEvent() (ep epollEvent) {
  57. if event&EventRead != 0 {
  58. ep |= EPOLLIN | EPOLLRDHUP
  59. }
  60. if event&EventWrite != 0 {
  61. ep |= EPOLLOUT
  62. }
  63. if event&EventOneShot != 0 {
  64. ep |= EPOLLONESHOT
  65. }
  66. if event&EventEdgeTriggered != 0 {
  67. ep |= EPOLLET
  68. }
  69. return
  70. }
  71. // epoll is a single epoll instance
  72. type epoll struct {
  73. mu sync.RWMutex
  74. fd int
  75. eventFD int
  76. closed bool
  77. waitDone chan struct{}
  78. callback map[int]func(epollEvent)
  79. }
  80. type epollConfig struct {
  81. OnWaitError func(error)
  82. }
  83. func newEpoll(c *epollConfig) (*epoll, error) {
  84. fd, err := unix.EpollCreate(1)
  85. if err != nil {
  86. log.Printf("EpollCreate(0): %v\n", err)
  87. return nil, err
  88. }
  89. r0, _, errno := unix.Syscall(unix.SYS_EVENTFD2, 0, 0, 0)
  90. if errno != 0 {
  91. log.Printf("Syscall(SYS_EVENTFD2): %v\n", err)
  92. return nil, errno
  93. }
  94. eventFD := int(r0)
  95. if err = unix.EpollCtl(fd, unix.EPOLL_CTL_ADD, eventFD, &unix.EpollEvent{
  96. Events: unix.EPOLLIN,
  97. Fd: int32(eventFD),
  98. }); err != nil {
  99. unix.Close(fd)
  100. unix.Close(eventFD)
  101. return nil, err
  102. }
  103. poll := &epoll{
  104. fd: fd,
  105. eventFD: eventFD,
  106. callback: make(map[int]func(epollEvent)),
  107. waitDone: make(chan struct{}),
  108. }
  109. go poll.wait(c.OnWaitError)
  110. return poll, nil
  111. }
  112. func (ep *epoll) wait(onError func(error)) {
  113. defer func() {
  114. if err := unix.Close(ep.fd); err != nil {
  115. if onError != nil {
  116. onError(err)
  117. } else {
  118. log.Printf("poll: epoll error: %v\n", err)
  119. }
  120. }
  121. close(ep.waitDone)
  122. }()
  123. events := make([]unix.EpollEvent, maxWaitEventsBegin)
  124. callbacks := make([]func(epollEvent), 0, maxWaitEventsBegin)
  125. for {
  126. n, err := unix.EpollWait(ep.fd, events, -1)
  127. if err != nil {
  128. if isTemporaryError(err) {
  129. continue
  130. }
  131. if onError != nil {
  132. onError(err)
  133. }
  134. return
  135. }
  136. callbacks = callbacks[:n]
  137. ep.mu.RLock()
  138. for i := 0; i < n; i++ {
  139. fd := int(events[i].Fd)
  140. if fd == ep.eventFD {
  141. ep.mu.RUnlock()
  142. return
  143. }
  144. callbacks[i] = ep.callback[fd]
  145. }
  146. ep.mu.RUnlock()
  147. for i := 0; i < n; i++ {
  148. if fn := callbacks[i]; fn != nil {
  149. fn(epollEvent(events[i].Events))
  150. callbacks[i] = nil
  151. }
  152. }
  153. if n == len(events) && n<<1 <= maxWaitEventsStop {
  154. events = make([]unix.EpollEvent, n<<1)
  155. callbacks = make([]func(epollEvent), 0, n<<1)
  156. }
  157. }
  158. }
  159. var epollCloseBytes = []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  160. func (ep *epoll) Close() error {
  161. ep.mu.Lock()
  162. if ep.closed {
  163. ep.mu.Unlock()
  164. return ErrClosed
  165. }
  166. ep.closed = true
  167. if _, err := unix.Write(ep.eventFD, epollCloseBytes); err != nil {
  168. ep.mu.Unlock()
  169. return err
  170. }
  171. ep.mu.Unlock()
  172. <-ep.waitDone
  173. if err := unix.Close(ep.eventFD); err != nil {
  174. return err
  175. }
  176. ep.mu.Lock()
  177. callback := ep.callback
  178. ep.callback = nil
  179. ep.mu.Unlock()
  180. for _, fn := range callback {
  181. if fn != nil {
  182. fn(EPOLLCLOSED)
  183. }
  184. }
  185. return nil
  186. }
  187. func (ep *epoll) Add(fd int, events epollEvent, cb func(epollEvent)) error {
  188. ev := &unix.EpollEvent{
  189. Events: uint32(events),
  190. Fd: int32(fd),
  191. }
  192. ep.mu.Lock()
  193. defer ep.mu.Unlock()
  194. if ep.closed {
  195. return ErrClosed
  196. }
  197. if _, ok := ep.callback[fd]; ok {
  198. return ErrRegistered
  199. }
  200. ep.callback[fd] = cb
  201. return unix.EpollCtl(ep.fd, unix.EPOLL_CTL_ADD, fd, ev)
  202. }
  203. func (ep *epoll) Del(fd int) error {
  204. ep.mu.Lock()
  205. defer ep.mu.Unlock()
  206. if ep.closed {
  207. return ErrClosed
  208. }
  209. if _, ok := ep.callback[fd]; !ok {
  210. return ErrNotRegistered
  211. }
  212. delete(ep.callback, fd)
  213. return unix.EpollCtl(ep.fd, unix.EPOLL_CTL_DEL, fd, nil)
  214. }
  215. func (ep *epoll) Mod(fd int, events epollEvent) error {
  216. ev := &unix.EpollEvent{
  217. Events: uint32(events),
  218. Fd: int32(fd),
  219. }
  220. ep.mu.Lock()
  221. defer ep.mu.Unlock()
  222. if ep.closed {
  223. return ErrClosed
  224. }
  225. if _, ok := ep.callback[fd]; !ok {
  226. return ErrNotRegistered
  227. }
  228. return unix.EpollCtl(ep.fd, unix.EPOLL_CTL_MOD, fd, ev)
  229. }