From 1fefda2e007659e1a8578bae9ab56d28d00a9f4c Mon Sep 17 00:00:00 2001 From: aherlihy Date: Tue, 30 Jun 2015 12:40:29 -0400 Subject: [PATCH] PYTHON-307 Replace select with poll on platforms that support it. --- pymongo/network.py | 18 +++++++++++++++++- test/test_pooling.py | 8 ++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pymongo/network.py b/pymongo/network.py index 049d200c4..d38d30495 100644 --- a/pymongo/network.py +++ b/pymongo/network.py @@ -17,6 +17,17 @@ import select import struct +_HAS_POLL = True +_poller = None +_EVENT_MASK = 0 +try: + from select import poll + _poller = poll() + _EVENT_MASK = (select.POLLIN | select.POLLPRI | select.POLLERR | + select.POLLHUP | select.POLLNVAL) +except ImportError: + _HAS_POLL = False + from pymongo import helpers, message from pymongo.errors import AutoReconnect @@ -93,7 +104,12 @@ def socket_closed(sock): """Return True if we know socket has been closed, False otherwise. """ try: - rd, _, _ = select.select([sock], [], [], 0) + if _HAS_POLL: + _poller.register(sock, _EVENT_MASK) + rd = _poller.poll(0) + _poller.unregister(sock) + else: + rd, _, _ = select.select([sock], [], [], 0) # Any exception here is equally bad (select.error, ValueError, etc.). except: return True diff --git a/test/test_pooling.py b/test/test_pooling.py index ec78056bc..718cca76c 100644 --- a/test/test_pooling.py +++ b/test/test_pooling.py @@ -241,6 +241,14 @@ class TestPooling(_TestPoolingBase): with cx_pool.get_socket({}): pass + def test_socket_closed(self): + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(('localhost', 27017)) + self.assertFalse(socket_closed(s)) + s.close() + self.assertTrue(socket_closed(s)) + def test_return_socket_after_reset(self): pool = self.create_pool() with pool.get_socket({}) as sock: