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

Async is broken on Windows

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 4.9
    • Affects Version/s: None
    • Component/s: None
    • None
    • Python Drivers
    • Not Needed
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      Async is still broken on Windows:

       [2024/08/08 07:46:25.942] FAILURE: pymongo.errors.AutoReconnect: localhost:27017: [WinError 87] The parameter is incorrect (configured timeouts: connectTimeoutMS: 20000.0ms) ()
       [2024/08/08 07:46:25.942] self = AsyncConnection(<socket.socket [closed] fd=-1, family=2, type=1, proto=0>) CLOSED at 2536934578976
       [2024/08/08 07:46:25.942] dbname = 'pymongo_test'
       [2024/08/08 07:46:25.942] spec = {'$db': 'pymongo_test', 'createIndexes': 't', 'indexes': [{'key': {'x': 1}, 'name': 'x_1'}], 'lsid': {'id': Binary(b'\xbb\x07Z\xf1\xcb\xc6N%\x87`e\xa1\x04OT?', 4)}}
       [2024/08/08 07:46:25.942] read_preference = Primary()
       [2024/08/08 07:46:25.942] codec_options = CodecOptions(document_class=dict, tz_aware=False, uuid_representation=UuidRepresentation.UNSPECIFIED, unicode_decode_e...ne, type_registry=TypeRegistry(type_codecs=[], fallback_encoder=None), datetime_conversion=DatetimeConversion.DATETIME)
       [2024/08/08 07:46:25.942] check = True, allowable_errors = None, read_concern = None
       [2024/08/08 07:46:25.942] write_concern = WriteConcern(), parse_write_concern_error = True
       [2024/08/08 07:46:25.942] collation = None
       [2024/08/08 07:46:25.942] session = <pymongo.asynchronous.client_session.AsyncClientSession object at 0x0000024EAF164380>
       [2024/08/08 07:46:25.942] client = AsyncMongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True)
       [2024/08/08 07:46:25.942] retryable_write = False, publish_events = True, user_fields = None
       [2024/08/08 07:46:25.942] exhaust_allowed = False
       [2024/08/08 07:46:25.942]     @_handle_reauth
       [2024/08/08 07:46:25.942]     async def command(
       [2024/08/08 07:46:25.942]         self,
       [2024/08/08 07:46:25.942]         dbname: str,
       [2024/08/08 07:46:25.942]         spec: MutableMapping[str, Any],
       [2024/08/08 07:46:25.942]         read_preference: _ServerMode = ReadPreference.PRIMARY,
       [2024/08/08 07:46:25.942]         codec_options: CodecOptions = DEFAULT_CODEC_OPTIONS,
       [2024/08/08 07:46:25.942]         check: bool = True,
       [2024/08/08 07:46:25.942]         allowable_errors: Optional[Sequence[Union[str, int]]] = None,
       [2024/08/08 07:46:25.942]         read_concern: Optional[ReadConcern] = None,
       [2024/08/08 07:46:25.942]         write_concern: Optional[WriteConcern] = None,
       [2024/08/08 07:46:25.942]         parse_write_concern_error: bool = False,
       [2024/08/08 07:46:25.942]         collation: Optional[_CollationIn] = None,
       [2024/08/08 07:46:25.942]         session: Optional[AsyncClientSession] = None,
       [2024/08/08 07:46:25.942]         client: Optional[AsyncMongoClient] = None,
       [2024/08/08 07:46:25.942]         retryable_write: bool = False,
       [2024/08/08 07:46:25.942]         publish_events: bool = True,
       [2024/08/08 07:46:25.942]         user_fields: Optional[Mapping[str, Any]] = None,
       [2024/08/08 07:46:25.942]         exhaust_allowed: bool = False,
       [2024/08/08 07:46:25.942]     ) -> dict[str, Any]:
       [2024/08/08 07:46:25.942]         """Execute a command or raise an error.
       [2024/08/08 07:46:25.942]     
       [2024/08/08 07:46:25.942]         :param dbname: name of the database on which to run the command
       [2024/08/08 07:46:25.942]         :param spec: a command document as a dict, SON, or mapping object
       [2024/08/08 07:46:25.942]         :param read_preference: a read preference
       [2024/08/08 07:46:25.942]         :param codec_options: a CodecOptions instance
       [2024/08/08 07:46:25.942]         :param check: raise OperationFailure if there are errors
       [2024/08/08 07:46:25.942]         :param allowable_errors: errors to ignore if `check` is True
       [2024/08/08 07:46:25.942]         :param read_concern: The read concern for this command.
       [2024/08/08 07:46:25.942]         :param write_concern: The write concern for this command.
       [2024/08/08 07:46:25.942]         :param parse_write_concern_error: Whether to parse the
       [2024/08/08 07:46:25.942]             ``writeConcernError`` field in the command response.
       [2024/08/08 07:46:25.942]         :param collation: The collation for this command.
       [2024/08/08 07:46:25.942]         :param session: optional AsyncClientSession instance.
       [2024/08/08 07:46:25.942]         :param client: optional AsyncMongoClient for gossipping $clusterTime.
       [2024/08/08 07:46:25.942]         :param retryable_write: True if this command is a retryable write.
       [2024/08/08 07:46:25.942]         :param publish_events: Should we publish events for this command?
       [2024/08/08 07:46:25.942]         :param user_fields: Response fields that should be decoded
       [2024/08/08 07:46:25.942]             using the TypeDecoders from codec_options, passed to
       [2024/08/08 07:46:25.942]             bson._decode_all_selective.
       [2024/08/08 07:46:25.942]         """
       [2024/08/08 07:46:25.942]         self.validate_session(client, session)
       [2024/08/08 07:46:25.942]         session = _validate_session_write_concern(session, write_concern)
       [2024/08/08 07:46:25.942]     
       [2024/08/08 07:46:25.942]         # Ensure command name remains in first place.
       [2024/08/08 07:46:25.942]         if not isinstance(spec, ORDERED_TYPES):  # type:ignore[arg-type]
       [2024/08/08 07:46:25.942]             spec = dict(spec)
       [2024/08/08 07:46:25.942]     
       [2024/08/08 07:46:25.942]         if not (write_concern is None or write_concern.acknowledged or collation is None):
       [2024/08/08 07:46:25.942]             raise ConfigurationError("Collation is unsupported for unacknowledged writes.")
       [2024/08/08 07:46:25.942]     
       [2024/08/08 07:46:25.942]         self.add_server_api(spec)
       [2024/08/08 07:46:25.942]         if session:
       [2024/08/08 07:46:25.942]             session._apply_to(spec, retryable_write, read_preference, self)
       [2024/08/08 07:46:25.942]         self.send_cluster_time(spec, session, client)
       [2024/08/08 07:46:25.942]         listeners = self.listeners if publish_events else None
       [2024/08/08 07:46:25.942]         unacknowledged = bool(write_concern and not write_concern.acknowledged)
       [2024/08/08 07:46:25.942]         if self.op_msg_enabled:
       [2024/08/08 07:46:25.942]             self._raise_if_not_writable(unacknowledged)
       [2024/08/08 07:46:25.942]         try:
       [2024/08/08 07:46:25.942] >           return await command(
       [2024/08/08 07:46:25.942]                 self,
       [2024/08/08 07:46:25.942]                 dbname,
       [2024/08/08 07:46:25.942]                 spec,
       [2024/08/08 07:46:25.942]                 self.is_mongos,
       [2024/08/08 07:46:25.942]                 read_preference,
       [2024/08/08 07:46:25.942]                 codec_options,
       [2024/08/08 07:46:25.942]                 session,
       [2024/08/08 07:46:25.942]                 client,
       [2024/08/08 07:46:25.942]                 check,
       [2024/08/08 07:46:25.942]                 allowable_errors,
       [2024/08/08 07:46:25.942]                 self.address,
       [2024/08/08 07:46:25.942]                 listeners,
       [2024/08/08 07:46:25.942]                 self.max_bson_size,
       [2024/08/08 07:46:25.942]                 read_concern,
       [2024/08/08 07:46:25.942]                 parse_write_concern_error=parse_write_concern_error,
       [2024/08/08 07:46:25.942]                 collation=collation,
       [2024/08/08 07:46:25.942]                 compression_ctx=self.compression_context,
       [2024/08/08 07:46:25.942]                 use_op_msg=self.op_msg_enabled,
       [2024/08/08 07:46:25.942]                 unacknowledged=unacknowledged,
       [2024/08/08 07:46:25.942]                 user_fields=user_fields,
       [2024/08/08 07:46:25.942]                 exhaust_allowed=exhaust_allowed,
       [2024/08/08 07:46:25.942]                 write_concern=write_concern,
       [2024/08/08 07:46:25.942]             )
       [2024/08/08 07:46:25.942] pymongo\asynchronous\pool.py:538: 
       [2024/08/08 07:46:25.942] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
       [2024/08/08 07:46:25.942] pymongo\asynchronous\network.py:203: in command
       [2024/08/08 07:46:25.942]     await async_sendall(conn.conn, msg)
       [2024/08/08 07:46:25.942] pymongo\network_layer.py:43: in async_sendall
       [2024/08/08 07:46:25.942]     await asyncio.wait_for(loop.sock_sendall(socket, buf), timeout=timeout)  # type: ignore[arg-type]
       [2024/08/08 07:46:25.942] C:\python\Python312\Lib\asyncio\tasks.py:520: in wait_for
       [2024/08/08 07:46:25.942]     return await fut
       [2024/08/08 07:46:25.942] C:\python\Python312\Lib\asyncio\proactor_events.py:721: in sock_sendall
       [2024/08/08 07:46:25.942]     return await self._proactor.send(sock, data)
       [2024/08/08 07:46:25.942] C:\python\Python312\Lib\asyncio\windows_events.py:539: in send
       [2024/08/08 07:46:25.942]     self._register_with_iocp(conn)
       [2024/08/08 07:46:25.942] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
       [2024/08/08 07:46:25.942] self = <IocpProactor overlapped#=0 result#=0 closed>
       [2024/08/08 07:46:25.942] obj = <socket.socket [closed] fd=-1, family=2, type=1, proto=0>
       [2024/08/08 07:46:25.942]     def _register_with_iocp(self, obj):
       [2024/08/08 07:46:25.942]         # To get notifications of finished ops on this objects sent to the
       [2024/08/08 07:46:25.942]         # completion port, were must register the handle.
       [2024/08/08 07:46:25.942]         if obj not in self._registered:
       [2024/08/08 07:46:25.942]             self._registered.add(obj)
       [2024/08/08 07:46:25.942] >           _overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
       [2024/08/08 07:46:25.942] E           OSError: [WinError 87] The parameter is incorrect
       [2024/08/08 07:46:25.942] C:\python\Python312\Lib\asyncio\windows_events.py:709: OSError
       [2024/08/08 07:46:25.942] The above exception was the direct cause of the following exception:
       [2024/08/08 07:46:25.942] self = <test.asynchronous.test_client.TestClient testMethod=test_dict_hints_create_index>
       [2024/08/08 07:46:25.942]     async def test_dict_hints_create_index(self):
       [2024/08/08 07:46:25.942] >       await self.db.t.create_index({"x": pymongo.ASCENDING})
       [2024/08/08 07:46:25.942] test\asynchronous\test_client.py:2031: 
       [2024/08/08 07:46:25.942] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
       [2024/08/08 07:46:25.942] pymongo\asynchronous\collection.py:2336: in create_index
       [2024/08/08 07:46:25.942]     return (await self._create_indexes([index], session, **cmd_options))[0]
       [2024/08/08 07:46:25.942] pymongo\_csot.py:110: in csot_wrapper
       [2024/08/08 07:46:25.942]     return await func(self, *args, **kwargs)
       [2024/08/08 07:46:25.942] pymongo\asynchronous\collection.py:2210: in _create_indexes
       [2024/08/08 07:46:25.942]     await self._command(
       [2024/08/08 07:46:25.942] pymongo\asynchronous\collection.py:593: in _command
       [2024/08/08 07:46:25.942]     return await conn.command(
       [2024/08/08 07:46:25.942] pymongo\asynchronous\helpers.py:45: in inner
       [2024/08/08 07:46:25.942]     return await func(*args, **kwargs)
       [2024/08/08 07:46:25.942] pymongo\asynchronous\pool.py:566: in command
       [2024/08/08 07:46:25.942]     self._raise_connection_failure(error)
       [2024/08/08 07:46:25.942] pymongo\asynchronous\pool.py:765: in _raise_connection_failure
       [2024/08/08 07:46:25.942]     _raise_connection_failure(self.address, error, timeout_details=details)
       [2024/08/08 07:46:25.942] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
       [2024/08/08 07:46:25.942] address = ('localhost', 27017)
       [2024/08/08 07:46:25.942] error = OSError(22, 'The parameter is incorrect', None, 87, None)
       [2024/08/08 07:46:25.942] msg_prefix = None, timeout_details = {'connectTimeoutMS': 20000.0}
       [2024/08/08 07:46:25.942]     def _raise_connection_failure(
       [2024/08/08 07:46:25.942]         address: Any,
       [2024/08/08 07:46:25.942]         error: Exception,
       [2024/08/08 07:46:25.942]         msg_prefix: Optional[str] = None,
       [2024/08/08 07:46:25.942]         timeout_details: Optional[dict[str, float]] = None,
       [2024/08/08 07:46:25.942]     ) -> NoReturn:
       [2024/08/08 07:46:25.942]         """Convert a socket.error to ConnectionFailure and raise it."""
       [2024/08/08 07:46:25.942]         host, port = address
       [2024/08/08 07:46:25.942]         # If connecting to a Unix socket, port will be None.
       [2024/08/08 07:46:25.942]         if port is not None:
       [2024/08/08 07:46:25.942]             msg = "%s:%d: %s" % (host, port, error)
       [2024/08/08 07:46:25.942]         else:
       [2024/08/08 07:46:25.942]             msg = f"{host}: {error}"
       [2024/08/08 07:46:25.942]         if msg_prefix:
       [2024/08/08 07:46:25.942]             msg = msg_prefix + msg
       [2024/08/08 07:46:25.942]         if "configured timeouts" not in msg:
       [2024/08/08 07:46:25.942]             msg += format_timeout_details(timeout_details)
       [2024/08/08 07:46:25.942]         if isinstance(error, socket.timeout):
       [2024/08/08 07:46:25.942]             raise NetworkTimeout(msg) from error
       [2024/08/08 07:46:25.942]         elif isinstance(error, SSLError) and "timed out" in str(error):
       [2024/08/08 07:46:25.942]             # Eventlet does not distinguish TLS network timeouts from other
       [2024/08/08 07:46:25.942]             # SSLErrors (https://github.com/eventlet/eventlet/issues/692).
       [2024/08/08 07:46:25.942]             # Luckily, we can work around this limitation because the phrase
       [2024/08/08 07:46:25.942]             # 'timed out' appears in all the timeout related SSLErrors raised.
       [2024/08/08 07:46:25.942]             raise NetworkTimeout(msg) from error
       [2024/08/08 07:46:25.942]         else:
       [2024/08/08 07:46:25.942] >           raise AutoReconnect(msg) from error
       [2024/08/08 07:46:25.942] E           pymongo.errors.AutoReconnect: localhost:27017: [WinError 87] The parameter is incorrect (configured timeouts: connectTimeoutMS: 20000.0ms)
       [2024/08/08 07:46:25.942] pymongo\asynchronous\pool.py:208: AutoReconnect
      

      https://evergreen.mongodb.com/task/mongo_python_driver_tests_windows_python_version__platform~windows_64_vsMulti_small_auth_ssl~noauth_nossl_python_version_windows~3.12_test_3.6_standalone_13cf110f016b36926ce836552c7b324b0ea7dba0_24_08_07_23_17_48

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

              Created:
              Updated:
              Resolved: