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.
12 "golang.org/x/sys/unix"
15 type fdPoller struct {
16 fd int // File descriptor (as returned by the inotify_init() syscall)
17 epfd int // Epoll file descriptor
18 pipe [2]int // Pipe for waking up
21 func emptyPoller(fd int) *fdPoller {
22 poller := new(fdPoller)
30 // Create a new inotify poller.
31 // This creates an inotify handler, and an epoll handler.
32 func newFdPoller(fd int) (*fdPoller, error) {
34 poller := emptyPoller(fd)
43 poller.epfd, errno = unix.EpollCreate1(0)
44 if poller.epfd == -1 {
47 // Create pipe; pipe[0] is the read end, pipe[1] the write end.
48 errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK)
53 // Register inotify fd with epoll
54 event := unix.EpollEvent{
58 errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event)
63 // Register pipe fd with epoll
64 event = unix.EpollEvent{
65 Fd: int32(poller.pipe[0]),
68 errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event)
77 // Returns true if something is ready to be read,
78 // false if there is not.
79 func (poller *fdPoller) wait() (bool, error) {
80 // 3 possible events per fd, and 2 fds, makes a maximum of 6 events.
81 // I don't know whether epoll_wait returns the number of events returned,
82 // or the total number of events ready.
83 // I decided to catch both by making the buffer one larger than the maximum.
84 events := make([]unix.EpollEvent, 7)
86 n, errno := unix.EpollWait(poller.epfd, events, -1)
88 if errno == unix.EINTR {
94 // If there are no events, try again.
98 // This should never happen. More events were returned than should be possible.
99 return false, errors.New("epoll_wait returned more events than I know what to do with")
105 for _, event := range ready {
106 if event.Fd == int32(poller.fd) {
107 if event.Events&unix.EPOLLHUP != 0 {
108 // This should not happen, but if it does, treat it as a wakeup.
111 if event.Events&unix.EPOLLERR != 0 {
112 // If an error is waiting on the file descriptor, we should pretend
113 // something is ready to read, and let unix.Read pick up the error.
116 if event.Events&unix.EPOLLIN != 0 {
117 // There is data to read.
121 if event.Fd == int32(poller.pipe[0]) {
122 if event.Events&unix.EPOLLHUP != 0 {
123 // Write pipe descriptor was closed, by us. This means we're closing down the
124 // watcher, and we should wake up.
126 if event.Events&unix.EPOLLERR != 0 {
127 // If an error is waiting on the pipe file descriptor.
128 // This is an absolute mystery, and should never ever happen.
129 return false, errors.New("Error on the pipe descriptor.")
131 if event.Events&unix.EPOLLIN != 0 {
132 // This is a regular wakeup, so we have to clear the buffer.
133 err := poller.clearWake()
141 if epollhup || epollerr || epollin {
148 // Close the write end of the poller.
149 func (poller *fdPoller) wake() error {
150 buf := make([]byte, 1)
151 n, errno := unix.Write(poller.pipe[1], buf)
153 if errno == unix.EAGAIN {
154 // Buffer is full, poller will wake.
162 func (poller *fdPoller) clearWake() error {
163 // You have to be woken up a LOT in order to get to 100!
164 buf := make([]byte, 100)
165 n, errno := unix.Read(poller.pipe[0], buf)
167 if errno == unix.EAGAIN {
168 // Buffer is empty, someone else cleared our wake.
176 // Close all poller file descriptors, but not the one passed to it.
177 func (poller *fdPoller) close() {
178 if poller.pipe[1] != -1 {
179 unix.Close(poller.pipe[1])
181 if poller.pipe[0] != -1 {
182 unix.Close(poller.pipe[0])
184 if poller.epfd != -1 {
185 unix.Close(poller.epfd)