In pymongo 3.7 SocketChecker, why the _EVENT_MASK had a select.POLLIN | select.POLLPRI?
From My Understanding, pool use the SocketChecker.socket_closed to check the socket obj status, reconnect this socket obj if it is select.POLLERR,select.POLLHUP, select.POLLNVAL.
but the socket obj had select.POLLIN, it will be reconnect?
pymongo/pool.py
class Pool:
def __init__(self, address, options, handshake=True):
……
self.socket_checker = SocketChecker()
def _check(self, sock_info):
"""This side-effecty function checks if this socket has been idle for
for longer than the max idle time, or if the socket has been closed by
some external network error, and if so, attempts to create a new
socket. If this connection attempt fails we raise the
ConnectionFailure.
Checking sockets lets us avoid seeing *some*
:class:`~pymongo.errors.AutoReconnect` exceptions on server
hiccups, etc. We only check if the socket was closed by an external
error if it has been > 1 second since the socket was checked into the
pool, to keep performance reasonable - we can't avoid AutoReconnects
completely anyway.
"""
idle_time_seconds = sock_info.idle_time_seconds()
# If socket is idle, open a new one.
if (self.opts.max_idle_time_seconds is not None and
idle_time_seconds > self.opts.max_idle_time_seconds):
sock_info.close()
return self.connect()
if (self._check_interval_seconds is not None and (
0 == self._check_interval_seconds or
idle_time_seconds > self._check_interval_seconds)):
if self.socket_checker.socket_closed(sock_info.sock):
sock_info.close()
return self.connect()
return sock_info
pymongo/network.py
try:
from select import poll
_EVENT_MASK = (
select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP)
except ImportError:
_HAS_POLL = False
class SocketChecker(object):
def __init__(self):
if _HAS_POLL:
self._lock = threading.Lock()
self._poller = poll()
else:
self._lock = None
self._poller = None
def socket_closed(self, sock):
"""Return True if we know socket has been closed, False otherwise.
"""
while True:
try:
if self._poller:
with self._lock:
self._poller.register(sock, _EVENT_MASK)
try:
rd = self._poller.poll(0)
finally:
self._poller.unregister(sock)
else:
rd, _, _ = select.select([sock], [], [], 0)
except (RuntimeError, KeyError):
# RuntimeError is raised during a concurrent poll. KeyError
# is raised by unregister if the socket is not in the poller.
# These errors should not be possible since we protect the
# poller with a mutex.
raise
except ValueError:
# ValueError is raised by register/unregister/select if the
# socket file descriptor is negative or outside the range for
# select (> 1023).
return True
except (_SELECT_ERROR, IOError) as exc:
if _errno_from_exception(exc) in (errno.EINTR, errno.EAGAIN):
continue
return True
except Exception:
# Any other exceptions should be attributed to a closed
# or invalid socket.
return True
return len(rd) > 0
I try to print the rd result, I found some socket obj had select.POLLIN event and it return True, socket obj will be reconnect.