From 76caf7d41d532c619b679c8afbe34868db00387e Mon Sep 17 00:00:00 2001 From: David Wilson Date: Tue, 24 Jul 2018 16:04:14 -0700 Subject: [PATCH] issue #320: ignore kqueue events marked KQ_EV_ERROR. Since BasicStream.close() invokes _stop_transmit() followed by os.close(), and KqueuePoller._stop_transmit() defers the unsubscription until the IO loop resumes, kqueue generates an error event for the associated FD, even though the changelist includes an unsubscription command for the FD. We could fix this by deferring close() until after the IO loop has run once (simply by calling .defer()), but that generates extra wakeups for no real reason. Instead simply notice the error event and log it, rather than treating it as a legitimate event. Another approach to fixing this would be to process _stop_receive()/_stop_transmit() eagerly, however that entails making more syscalls. Closes #320. --- mitogen/parent.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mitogen/parent.py b/mitogen/parent.py index 38484874..50d78efd 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -566,7 +566,10 @@ class KqueuePoller(mitogen.core.Poller): changelist, 32, timeout) for event in events: fd = event.ident - if event.filter == select.KQ_FILTER_READ and fd in self._rfds: + if event.flags & select.KQ_EV_ERROR: + LOG.debug('ignoring stale event for fd %r: errno=%d: %s', + fd, event.data, errno.errorcode.get(event.data)) + elif event.filter == select.KQ_FILTER_READ and fd in self._rfds: # Events can still be read for an already-discarded fd. mitogen.core._vv and IOLOG.debug('%r: POLLIN: %r', self, fd) yield self._rfds[fd]