Skip to content

PYTHON-2443 Fix TypeError when pyOpenSSL socket has timeout of None (with regression test) #527

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions pymongo/socket_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(self):
self._poller = None

def select(self, sock, read=False, write=False, timeout=0):
"""Select for reads or writes with a timeout in seconds.
"""Select for reads or writes with a timeout in seconds (or None).

Returns True if the socket is readable/writable, False on timeout.
"""
Expand All @@ -57,7 +57,8 @@ def select(self, sock, read=False, write=False, timeout=0):
try:
# poll() timeout is in milliseconds. select()
# timeout is in seconds.
res = self._poller.poll(timeout * 1000)
timeout_ = None if timeout is None else timeout * 1000
res = self._poller.poll(timeout_)
# poll returns a possibly-empty list containing
# (fd, event) 2-tuples for the descriptors that have
# events or errors to report. Return True if the list
Expand Down
36 changes: 35 additions & 1 deletion test/test_pooling.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@
import threading
import time

from pymongo import MongoClient
from bson.son import SON
from bson.codec_options import DEFAULT_CODEC_OPTIONS

from pymongo import MongoClient, message
from pymongo.errors import (AutoReconnect,
ConnectionFailure,
DuplicateKeyError,
Expand Down Expand Up @@ -259,6 +262,37 @@ def test_socket_closed(self):
s.close()
self.assertTrue(socket_checker.socket_closed(s))

def test_socket_checker(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((client_context.host, client_context.port))
socket_checker = SocketChecker()
# Socket has nothing to read.
self.assertFalse(socket_checker.select(s, read=True))
self.assertFalse(socket_checker.select(s, read=True, timeout=0))
self.assertFalse(socket_checker.select(s, read=True, timeout=.05))
# Socket is writable.
self.assertTrue(socket_checker.select(s, write=True, timeout=None))
self.assertTrue(socket_checker.select(s, write=True))
self.assertTrue(socket_checker.select(s, write=True, timeout=0))
self.assertTrue(socket_checker.select(s, write=True, timeout=.05))
# Make the socket readable
_, msg, _ = message.query(
0, 'admin.$cmd', 0, -1, SON([('isMaster', 1)]), None,
DEFAULT_CODEC_OPTIONS)
s.sendall(msg)
# Block until the socket is readable.
self.assertTrue(socket_checker.select(s, read=True, timeout=None))
self.assertTrue(socket_checker.select(s, read=True))
self.assertTrue(socket_checker.select(s, read=True, timeout=0))
self.assertTrue(socket_checker.select(s, read=True, timeout=.05))
# Socket is still writable.
self.assertTrue(socket_checker.select(s, write=True, timeout=None))
self.assertTrue(socket_checker.select(s, write=True))
self.assertTrue(socket_checker.select(s, write=True, timeout=0))
self.assertTrue(socket_checker.select(s, write=True, timeout=.05))
s.close()
self.assertTrue(socket_checker.socket_closed(s))

def test_return_socket_after_reset(self):
pool = self.create_pool()
with pool.get_socket({}) as sock:
Expand Down