bool process_inotify_input() { ssize_t len = read(inotify_fd, event_buf, EVENT_BUF_LEN); if (len < 0) { userlog(LOG_ERR, "read: %s", strerror(errno)); return false; } int i = 0; while (i < len) { struct inotify_event* event = (struct inotify_event*) &event_buf[i]; i += EVENT_SIZE + event->len; if (event->mask & IN_IGNORED) { continue; } if (event->mask & IN_Q_OVERFLOW) { userlog(LOG_INFO, "event queue overflow"); continue; } if (!process_inotify_event(event)) { return false; } } return true; }
static bool inot_root_consume_notify(watchman_global_watcher_t watcher, w_root_t *root, struct watchman_pending_collection *coll) { struct inot_root_state *state = root->watch; struct inotify_event *ine; char *iptr; int n; struct timeval now; unused_parameter(watcher); n = read(state->infd, &state->ibuf, sizeof(state->ibuf)); if (n == -1) { if (errno == EINTR) { return false; } w_log(W_LOG_FATAL, "read(%d, %zu): error %s\n", state->infd, sizeof(state->ibuf), strerror(errno)); } w_log(W_LOG_DBG, "inotify read: returned %d.\n", n); gettimeofday(&now, NULL); for (iptr = state->ibuf; iptr < state->ibuf + n; iptr = iptr + sizeof(*ine) + ine->len) { ine = (struct inotify_event*)iptr; process_inotify_event(root, coll, ine, now); if (root->cancelled) { return false; } } // It is possible that we can accumulate a set of pending_move // structs in move_map. This happens when a directory is moved // outside of the watched tree; we get the MOVE_FROM but never // get the MOVE_TO with the same cookie. To avoid leaking these, // we'll age out the move_map after processing a full set of // inotify events. We age out rather than delete all because // the MOVE_TO may yet be waiting to read in another go around. // We allow a somewhat arbitrary but practical grace period to // observe the corresponding MOVE_TO. if (w_ht_size(state->move_map) > 0) { w_ht_iter_t iter; if (w_ht_first(state->move_map, &iter)) do { struct pending_move *pending = w_ht_val_ptr(iter.value); if (now.tv_sec - pending->created > 5 /* seconds */) { w_log(W_LOG_DBG, "deleting pending move %s (moved outside of watch?)\n", pending->name->buf); w_ht_iter_del(state->move_map, &iter); } } while (w_ht_next(state->move_map, &iter)); } return true; }
static int inotify_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { sd_event *event = sd_event_source_get_event(s); ClockState *sp = userdata; union inotify_event_buffer buffer; struct inotify_event *e; ssize_t l; l = read(fd, &buffer, sizeof(buffer)); if (l < 0) { if (IN_SET(errno, EAGAIN, EINTR)) return 0; return log_warning_errno(errno, "Lost access to inotify: %m"); } FOREACH_INOTIFY_EVENT(e, buffer, l) process_inotify_event(event, sp, e); return 0; }