Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-2320

Jython SSL + poll fails with AttributeError: 'SSLSocket' object has no attribute 'channel'

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 3.11
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None

      It's no longer possible to reliably connect to Atlas clusters with Jython 2.7.0. Each SDAM monitor heartbeat fails with this error:

      >>> Exception in thread pymongo_server_monitor_thread:Traceback (most recent call last):
        File "/Users/shane/jython2.7.0/Lib/threading.py", line 222, in _Thread__bootstrap
          self.run()
        File "/Users/shane/jython2.7.0/Lib/threading.py", line 213, in run
          self._target(*self._args, **self._kwargs)
        File "pymongo/periodic_executor.py", line 125, in _run
          if not self._target():
        File "pymongo/monitor.py", line 46, in target
          monitor._run()
        File "pymongo/monitor.py", line 170, in _run
          self._server_description = self._check_server()
        File "pymongo/monitor.py", line 170, in _run
          self._server_description = self._check_server()
        File "pymongo/monitor.py", line 170, in _run
          self._server_description = self._check_server()
        File "pymongo/monitor.py", line 206, in _check_server
          return self._check_once()
        File "pymongo/monitor.py", line 206, in _check_server
          return self._check_once()
        File "pymongo/monitor.py", line 243, in _check_once
          response, round_trip_time = self._check_with_socket(sock_info)
        File "pymongo/monitor.py", line 274, in _check_with_socket
          response = conn._ismaster(cluster_time, None, None, None)
        File "pymongo/pool.py", line 579, in _ismaster
          doc = self.command('admin', cmd, publish_events=False,
        File "pymongo/pool.py", line 699, in command
          self._raise_connection_failure(error)
        File "pymongo/pool.py", line 683, in command
          return command(self, dbname, spec, slave_ok,
        File "pymongo/network.py", line 150, in command
          reply = receive_message(sock_info, request_id)
        File "pymongo/network.py", line 195, in receive_message
          length, _, response_to, op_code = _UNPACK_HEADER(
        File "pymongo/network.py", line 265, in _receive_data_on_socket
          wait_for_read(sock_info, deadline)
        File "pymongo/network.py", line 265, in _receive_data_on_socket
          wait_for_read(sock_info, deadline)
        File "pymongo/network.py", line 245, in wait_for_read
          readable = sock_info.socket_checker.select(
        File "pymongo/socket_checker.py", line 64, in select
          self._poller.unregister(sock)
        File "pymongo/socket_checker.py", line 57, in select
          res = self._poller.poll(timeout * 1000)
        File "/Users/shane/jython2.7.0/Lib/_socket.py", line 551, in poll
          result = self._handle_poll(partial(self.queue.poll, timeout_in_ns, TimeUnit.NANOSECONDS))
        File "/Users/shane/jython2.7.0/Lib/_socket.py", line 525, in _handle_poll
          fd, event = self._event_test(notification)
        File "/Users/shane/jython2.7.0/Lib/_socket.py", line 500, in _event_test
          if mask & POLLHUP and (notification.hangup or not notification.sock.channel):
      AttributeError: 'SSLSocket' object has no attribute 'channel'
      

      This appears to be a bug in Jython itself and is reproducible with Jython 2.7.0 and 2.7.1 and I've reported it here: https://bugs.jython.org/issue2900.

      This PyMongo regression was caused by the changes in PYTHON-2123. Before those changes (PyMongo <3.11) this Jython bug would cause each TLS socket to be recreated each time SocketChecker.socket_closed was called. In practice this means that each SDAM connection is recreated for each heartbeat and each application socket that remains idle in the connection pool for >1 second is also closed and automatically reopened.

      After PYTHON-2123, we use poll() to wait for a SDAM socket to be readable. This causes each heartbeat to fail with AttributeError: 'SSLSocket' object has no attribute 'channel' and marks the server Unknown.

      In summary, SSL+Jython kind of worked before but is now totally broken. If we want to fix this, we can skip the poll() logic on Jython.

      Edit: I've reported the bug to Jython here: https://bugs.jython.org/issue2900

            Assignee:
            shane.harvey@mongodb.com Shane Harvey
            Reporter:
            shane.harvey@mongodb.com Shane Harvey
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: