A lightweight mechanism to provide an *instant kickstart* to a Go web server instance upon changing any Go source files under the project directory (and its subdirectories).

inotify_poller.go 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build linux
  5. package fsnotify
  6. import (
  7. "errors"
  8. "golang.org/x/sys/unix"
  9. )
  10. type fdPoller struct {
  11. fd int // File descriptor (as returned by the inotify_init() syscall)
  12. epfd int // Epoll file descriptor
  13. pipe [2]int // Pipe for waking up
  14. }
  15. func emptyPoller(fd int) *fdPoller {
  16. poller := new(fdPoller)
  17. poller.fd = fd
  18. poller.epfd = -1
  19. poller.pipe[0] = -1
  20. poller.pipe[1] = -1
  21. return poller
  22. }
  23. // Create a new inotify poller.
  24. // This creates an inotify handler, and an epoll handler.
  25. func newFdPoller(fd int) (*fdPoller, error) {
  26. var errno error
  27. poller := emptyPoller(fd)
  28. defer func() {
  29. if errno != nil {
  30. poller.close()
  31. }
  32. }()
  33. poller.fd = fd
  34. // Create epoll fd
  35. poller.epfd, errno = unix.EpollCreate1(0)
  36. if poller.epfd == -1 {
  37. return nil, errno
  38. }
  39. // Create pipe; pipe[0] is the read end, pipe[1] the write end.
  40. errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK)
  41. if errno != nil {
  42. return nil, errno
  43. }
  44. // Register inotify fd with epoll
  45. event := unix.EpollEvent{
  46. Fd: int32(poller.fd),
  47. Events: unix.EPOLLIN,
  48. }
  49. errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event)
  50. if errno != nil {
  51. return nil, errno
  52. }
  53. // Register pipe fd with epoll
  54. event = unix.EpollEvent{
  55. Fd: int32(poller.pipe[0]),
  56. Events: unix.EPOLLIN,
  57. }
  58. errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event)
  59. if errno != nil {
  60. return nil, errno
  61. }
  62. return poller, nil
  63. }
  64. // Wait using epoll.
  65. // Returns true if something is ready to be read,
  66. // false if there is not.
  67. func (poller *fdPoller) wait() (bool, error) {
  68. // 3 possible events per fd, and 2 fds, makes a maximum of 6 events.
  69. // I don't know whether epoll_wait returns the number of events returned,
  70. // or the total number of events ready.
  71. // I decided to catch both by making the buffer one larger than the maximum.
  72. events := make([]unix.EpollEvent, 7)
  73. for {
  74. n, errno := unix.EpollWait(poller.epfd, events, -1)
  75. if n == -1 {
  76. if errno == unix.EINTR {
  77. continue
  78. }
  79. return false, errno
  80. }
  81. if n == 0 {
  82. // If there are no events, try again.
  83. continue
  84. }
  85. if n > 6 {
  86. // This should never happen. More events were returned than should be possible.
  87. return false, errors.New("epoll_wait returned more events than I know what to do with")
  88. }
  89. ready := events[:n]
  90. epollhup := false
  91. epollerr := false
  92. epollin := false
  93. for _, event := range ready {
  94. if event.Fd == int32(poller.fd) {
  95. if event.Events&unix.EPOLLHUP != 0 {
  96. // This should not happen, but if it does, treat it as a wakeup.
  97. epollhup = true
  98. }
  99. if event.Events&unix.EPOLLERR != 0 {
  100. // If an error is waiting on the file descriptor, we should pretend
  101. // something is ready to read, and let unix.Read pick up the error.
  102. epollerr = true
  103. }
  104. if event.Events&unix.EPOLLIN != 0 {
  105. // There is data to read.
  106. epollin = true
  107. }
  108. }
  109. if event.Fd == int32(poller.pipe[0]) {
  110. if event.Events&unix.EPOLLHUP != 0 {
  111. // Write pipe descriptor was closed, by us. This means we're closing down the
  112. // watcher, and we should wake up.
  113. }
  114. if event.Events&unix.EPOLLERR != 0 {
  115. // If an error is waiting on the pipe file descriptor.
  116. // This is an absolute mystery, and should never ever happen.
  117. return false, errors.New("Error on the pipe descriptor.")
  118. }
  119. if event.Events&unix.EPOLLIN != 0 {
  120. // This is a regular wakeup, so we have to clear the buffer.
  121. err := poller.clearWake()
  122. if err != nil {
  123. return false, err
  124. }
  125. }
  126. }
  127. }
  128. if epollhup || epollerr || epollin {
  129. return true, nil
  130. }
  131. return false, nil
  132. }
  133. }
  134. // Close the write end of the poller.
  135. func (poller *fdPoller) wake() error {
  136. buf := make([]byte, 1)
  137. n, errno := unix.Write(poller.pipe[1], buf)
  138. if n == -1 {
  139. if errno == unix.EAGAIN {
  140. // Buffer is full, poller will wake.
  141. return nil
  142. }
  143. return errno
  144. }
  145. return nil
  146. }
  147. func (poller *fdPoller) clearWake() error {
  148. // You have to be woken up a LOT in order to get to 100!
  149. buf := make([]byte, 100)
  150. n, errno := unix.Read(poller.pipe[0], buf)
  151. if n == -1 {
  152. if errno == unix.EAGAIN {
  153. // Buffer is empty, someone else cleared our wake.
  154. return nil
  155. }
  156. return errno
  157. }
  158. return nil
  159. }
  160. // Close all poller file descriptors, but not the one passed to it.
  161. func (poller *fdPoller) close() {
  162. if poller.pipe[1] != -1 {
  163. unix.Close(poller.pipe[1])
  164. }
  165. if poller.pipe[0] != -1 {
  166. unix.Close(poller.pipe[0])
  167. }
  168. if poller.epfd != -1 {
  169. unix.Close(poller.epfd)
  170. }
  171. }