diff --git a/pymongo/asynchronous/periodic_executor.py b/pymongo/asynchronous/periodic_executor.py index 337d10f133..f3d2fddba3 100644 --- a/pymongo/asynchronous/periodic_executor.py +++ b/pymongo/asynchronous/periodic_executor.py @@ -65,7 +65,17 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__}(name={self._name}) object at 0x{id(self):x}>" def _run_async(self) -> None: - asyncio.run(self._run()) # type: ignore[func-returns-value] + # The default asyncio loop implementation on Windows + # has issues with sharing sockets across loops (https://github.com/python/cpython/issues/122240) + # We explicitly use a different loop implementation here to prevent that issue + if sys.platform == "win32": + loop = asyncio.SelectorEventLoop() + try: + loop.run_until_complete(self._run()) # type: ignore[func-returns-value] + finally: + loop.close() + else: + asyncio.run(self._run()) # type: ignore[func-returns-value] def open(self) -> None: """Start. Multiple calls have no effect. diff --git a/pymongo/synchronous/periodic_executor.py b/pymongo/synchronous/periodic_executor.py index 43125016bc..525268b14b 100644 --- a/pymongo/synchronous/periodic_executor.py +++ b/pymongo/synchronous/periodic_executor.py @@ -65,7 +65,17 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__}(name={self._name}) object at 0x{id(self):x}>" def _run_async(self) -> None: - asyncio.run(self._run()) # type: ignore[func-returns-value] + # The default asyncio loop implementation on Windows + # has issues with sharing sockets across loops (https://github.com/python/cpython/issues/122240) + # We explicitly use a different loop implementation here to prevent that issue + if sys.platform == "win32": + loop = asyncio.SelectorEventLoop() + try: + loop.run_until_complete(self._run()) # type: ignore[func-returns-value] + finally: + loop.close() + else: + asyncio.run(self._run()) # type: ignore[func-returns-value] def open(self) -> None: """Start. Multiple calls have no effect. diff --git a/test/__init__.py b/test/__init__.py index b8bd185110..b603ae0a5b 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -79,6 +79,16 @@ _IS_SYNC = True +# The default asyncio loop implementation on Windows +# has issues with sharing sockets across loops (https://github.com/python/cpython/issues/122240) +# We explicitly use a different loop implementation here to prevent that issue +if ( + not _IS_SYNC + and sys.platform == "win32" + and asyncio.get_event_loop_policy() == asyncio.WindowsProactorEventLoopPolicy +): + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # type: ignore[attr-defined] + class ClientContext: client: MongoClient diff --git a/test/asynchronous/__init__.py b/test/asynchronous/__init__.py index 6f0785c4ff..878ef81bae 100644 --- a/test/asynchronous/__init__.py +++ b/test/asynchronous/__init__.py @@ -79,6 +79,16 @@ _IS_SYNC = False +# The default asyncio loop implementation on Windows +# has issues with sharing sockets across loops (https://github.com/python/cpython/issues/122240) +# We explicitly use a different loop implementation here to prevent that issue +if ( + not _IS_SYNC + and sys.platform == "win32" + and asyncio.get_event_loop_policy() == asyncio.WindowsProactorEventLoopPolicy +): + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) # type: ignore[attr-defined] + class AsyncClientContext: client: AsyncMongoClient