vendor/github.com/fsnotify/fsnotify/inotify_poller.go
changeset 265 05c40b36d3b2
parent 264 8f478162d991
child 266 80973a656b81
equal deleted inserted replaced
264:8f478162d991 265:05c40b36d3b2
     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 
       
     5 //go:build linux
       
     6 // +build linux
       
     7 
       
     8 package fsnotify
       
     9 
       
    10 import (
       
    11 	"errors"
       
    12 
       
    13 	"golang.org/x/sys/unix"
       
    14 )
       
    15 
       
    16 type fdPoller struct {
       
    17 	fd   int    // File descriptor (as returned by the inotify_init() syscall)
       
    18 	epfd int    // Epoll file descriptor
       
    19 	pipe [2]int // Pipe for waking up
       
    20 }
       
    21 
       
    22 func emptyPoller(fd int) *fdPoller {
       
    23 	poller := new(fdPoller)
       
    24 	poller.fd = fd
       
    25 	poller.epfd = -1
       
    26 	poller.pipe[0] = -1
       
    27 	poller.pipe[1] = -1
       
    28 	return poller
       
    29 }
       
    30 
       
    31 // Create a new inotify poller.
       
    32 // This creates an inotify handler, and an epoll handler.
       
    33 func newFdPoller(fd int) (*fdPoller, error) {
       
    34 	var errno error
       
    35 	poller := emptyPoller(fd)
       
    36 	defer func() {
       
    37 		if errno != nil {
       
    38 			poller.close()
       
    39 		}
       
    40 	}()
       
    41 
       
    42 	// Create epoll fd
       
    43 	poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC)
       
    44 	if poller.epfd == -1 {
       
    45 		return nil, errno
       
    46 	}
       
    47 	// Create pipe; pipe[0] is the read end, pipe[1] the write end.
       
    48 	errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC)
       
    49 	if errno != nil {
       
    50 		return nil, errno
       
    51 	}
       
    52 
       
    53 	// Register inotify fd with epoll
       
    54 	event := unix.EpollEvent{
       
    55 		Fd:     int32(poller.fd),
       
    56 		Events: unix.EPOLLIN,
       
    57 	}
       
    58 	errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event)
       
    59 	if errno != nil {
       
    60 		return nil, errno
       
    61 	}
       
    62 
       
    63 	// Register pipe fd with epoll
       
    64 	event = unix.EpollEvent{
       
    65 		Fd:     int32(poller.pipe[0]),
       
    66 		Events: unix.EPOLLIN,
       
    67 	}
       
    68 	errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event)
       
    69 	if errno != nil {
       
    70 		return nil, errno
       
    71 	}
       
    72 
       
    73 	return poller, nil
       
    74 }
       
    75 
       
    76 // Wait using epoll.
       
    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)
       
    85 	for {
       
    86 		n, errno := unix.EpollWait(poller.epfd, events, -1)
       
    87 		if n == -1 {
       
    88 			if errno == unix.EINTR {
       
    89 				continue
       
    90 			}
       
    91 			return false, errno
       
    92 		}
       
    93 		if n == 0 {
       
    94 			// If there are no events, try again.
       
    95 			continue
       
    96 		}
       
    97 		if n > 6 {
       
    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")
       
   100 		}
       
   101 		ready := events[:n]
       
   102 		epollhup := false
       
   103 		epollerr := false
       
   104 		epollin := false
       
   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.
       
   109 					epollhup = true
       
   110 				}
       
   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.
       
   114 					epollerr = true
       
   115 				}
       
   116 				if event.Events&unix.EPOLLIN != 0 {
       
   117 					// There is data to read.
       
   118 					epollin = true
       
   119 				}
       
   120 			}
       
   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.
       
   125 				}
       
   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.")
       
   130 				}
       
   131 				if event.Events&unix.EPOLLIN != 0 {
       
   132 					// This is a regular wakeup, so we have to clear the buffer.
       
   133 					err := poller.clearWake()
       
   134 					if err != nil {
       
   135 						return false, err
       
   136 					}
       
   137 				}
       
   138 			}
       
   139 		}
       
   140 
       
   141 		if epollhup || epollerr || epollin {
       
   142 			return true, nil
       
   143 		}
       
   144 		return false, nil
       
   145 	}
       
   146 }
       
   147 
       
   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)
       
   152 	if n == -1 {
       
   153 		if errno == unix.EAGAIN {
       
   154 			// Buffer is full, poller will wake.
       
   155 			return nil
       
   156 		}
       
   157 		return errno
       
   158 	}
       
   159 	return nil
       
   160 }
       
   161 
       
   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)
       
   166 	if n == -1 {
       
   167 		if errno == unix.EAGAIN {
       
   168 			// Buffer is empty, someone else cleared our wake.
       
   169 			return nil
       
   170 		}
       
   171 		return errno
       
   172 	}
       
   173 	return nil
       
   174 }
       
   175 
       
   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])
       
   180 	}
       
   181 	if poller.pipe[0] != -1 {
       
   182 		unix.Close(poller.pipe[0])
       
   183 	}
       
   184 	if poller.epfd != -1 {
       
   185 		unix.Close(poller.epfd)
       
   186 	}
       
   187 }