Skip to content

Conversation

kimvais
Copy link

@kimvais kimvais commented Nov 27, 2020

Fix for crash with the following stack trace when socket.getdefaulttimeout() is None

Traceback (most recent call last):
  File "<REDACTED>/manage.py", line 39, in <module>
    execute_from_command_line(sys.argv)
  File "<REDACTED>/dist-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
    utility.execute()
  File "<REDACTED>/dist-packages/django/core/management/__init__.py", line 356, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "<REDACTED>/dist-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "<REDACTED>/dist-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "<REDACTED>.py", line 365, in handle
    sources += <REDACTED>.objects.filter(**query)[:limit]
  File "<REDACTED>/dist-packages/mongoengine/queryset/manager.py", line 37, in __get__
    queryset = queryset_class(owner, owner._get_collection())
  File "<REDACTED>/dist-packages/mongoengine/document.py", line 211, in _get_collection
    db = cls._get_db()
  File "<REDACTED>/dist-packages/mongoengine/document.py", line 189, in _get_db
    return get_db(cls._meta.get("db_alias", DEFAULT_CONNECTION_NAME))
  File "<REDACTED>/dist-packages/mongoengine/connection.py", line 369, in get_db
    conn_settings["username"], conn_settings["password"], **auth_kwargs
  File "<REDACTED>/dist-packages/pymongo/database.py", line 1495, in authenticate
    connect=True)
  File "<REDACTED>/dist-packages/pymongo/mongo_client.py", line 780, in _cache_credentials
    with server.get_socket(all_credentials) as sock_info:
  File "<REDACTED>/contextlib.py", line 17, in __enter__
    return self.gen.next()
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 1225, in get_socket
    sock_info = self._get_socket(all_credentials)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 1275, in _get_socket
    sock_info = self.connect(all_credentials)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 1193, in connect
    sock_info.ismaster(all_credentials)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 546, in ismaster
    return self._ismaster(None, None, None, all_credentials)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 580, in _ismaster
    exhaust_allowed=awaitable)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 699, in command
    self._raise_connection_failure(error)
  File "<REDACTED>/dist-packages/pymongo/pool.py", line 694, in command
    exhaust_allowed=exhaust_allowed)
  File "<REDACTED>/dist-packages/pymongo/network.py", line 150, in command
    reply = receive_message(sock_info, request_id)
  File "<REDACTED>/dist-packages/pymongo/network.py", line 196, in receive_message    _receive_data_on_socket(sock_info, 16, deadline))
  File "<REDACTED>/dist-packages/pymongo/network.py", line 266, in _receive_data_on_socket
    chunk = sock_info.sock.recv(length)
  File "<REDACTED>/dist-packages/pymongo/pyopenssl_context.py", line 120, in recv
    return self._call(super(_sslConn, self).recv, *args, **kwargs)
  File "<REDACTED>/dist-packages/pymongo/pyopenssl_context.py", line 110, in _call    self, True, True, timeout)
  File "<REDACTED>/dist-packages/pymongo/socket_checker.py", line 60, in select
    res = self._poller.poll(timeout * 1000)
TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

@ShaneHarvey ShaneHarvey changed the title Fix a crash when SSL socket has timeout of None. PYTHON-2443 Fix TypeError when pyOpenSSL socket has timeout of None Nov 30, 2020
Copy link
Member

@ShaneHarvey ShaneHarvey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing this issue!

# timeout is in seconds.
res = self._poller.poll(timeout * 1000)
# socket.getdefaulttimeout() can return None
timeout_ = timeout * 1000 if timeout is not None else None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest reversing the if/else to shorten the line to <80 chars:

timeout_ = None if timeout is None else timeout * 1000

if write:
mask = mask | select.POLLOUT
self._poller.register(sock, mask)
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please update this method's docstring to say:

        """Select for reads or writes with a timeout in seconds (or None).

@ShaneHarvey
Copy link
Member

Thanks @kimvais, your fix will be merged in #527 (where I've added a test case).

@ShaneHarvey ShaneHarvey closed this Dec 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tracked-in-jira Ticket filed in Mongo's Jira system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants