{
EGC_GC;
+ if (revents & (POLLERR|POLLHUP))
+ LIBXL__EVENT_DISASTER(egc, "unexpected poll event on watch fd", 0, 0);
+
for (;;) {
char **event = xs_check_watch(CTX->xsh);
if (!event) {
/* again, stale slot entry */
return 0;
- int revents = fds[slot].revents & events;
+ assert(!(fds[slot].revents & POLLNVAL));
+
+ int revents = fds[slot].revents & (events | POLLERR | POLLHUP);
/* we mask in case requested events have changed */
return revents;
typedef struct libxl__ev_fd libxl__ev_fd;
typedef void libxl__ev_fd_callback(libxl__egc *egc, libxl__ev_fd *ev,
int fd, short events, short revents);
+ /* Note that revents may contain POLLERR or POLLHUP regardless of
+ * events; otherwise revents contains only bits in events. Contrary
+ * to the documentation for poll(2), POLLERR and POLLHUP can occur
+ * even if only POLLIN was set in events. (POLLNVAL is a fatal
+ * error and will cause libxl event machinery to fail an assertion.) */
struct libxl__ev_fd {
/* caller should include this in their own struct */
/* read-only for caller, who may read only when registered: */