classification
Title: WinError 10038 is raised when loop.sock_connect is wrapped with asyncio.wait_for
Type: behavior Stage:
Components: asyncio Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Alisue Lambda, asvetlov, yselivanov
Priority: normal Keywords:

Created on 2018-04-24 16:51 by Alisue Lambda, last changed 2018-08-07 09:24 by Alisue Lambda.

Files
File name Uploaded Description Edit
test.py Alisue Lambda, 2018-04-24 16:51 A minimal script to reproduce the issue on Windows 10 Pro
Messages (4)
msg315707 - (view) Author: Alisue Lambda (Alisue Lambda) Date: 2018-04-24 16:51
This is my first time to create an issue on the python bug tracker so let me know if I don't follow the rule which I need to follow.

# Summary

Using 'loop.sock_connect' with 'asyncio.wait_for' raises 'OSError [WinError 10038]' in Windows 10 Pro when timed-out.

# Detail

I use 'loop.sock_connect' to establish a TCP connection for checking if a particular port on a target host is available.
However, when I wrap the coroutine with 'asyncio.wait_for', the following exception is raised when the wrapped coroutine has timed-out.

    Traceback (most recent call last):
      File "C:\Users\alisue/test.py", line 41, in <module>
        loop.run_until_complete(test(loop))
      File "C:\Python36\lib\asyncio\base_events.py", line 454, in run_until_complete
        self.run_forever()
      File "C:\Python36\lib\asyncio\base_events.py", line 421, in run_forever
        self._run_once()
      File "C:\Python36\lib\asyncio\base_events.py", line 1395, in _run_once
        event_list = self._selector.select(timeout)
      File "C:\Python36\lib\selectors.py", line 323, in select
        r, w, _ = self._select(self._readers, self._writers, [], timeout)
      File "C:\Python36\lib\selectors.py", line 314, in _select
        r, w, x = select.select(r, w, w, timeout)
    OSError: [WinError 10038] ...........

While it is raised from 'lib\selectors.py', I cannot catch this exception so the event loop has halted.

The attached 'test.py' is a minimum script to reproduce the error.

Thanks.
msg315708 - (view) Author: Alisue Lambda (Alisue Lambda) Date: 2018-04-24 16:55
I should have mentioned that the script works well on macOS and Linux.
This issue exists only on Windows.
msg315709 - (view) Author: Alisue Lambda (Alisue Lambda) Date: 2018-04-24 17:21
I've found an workaround. The point is that 'with s' should be included in a coroutine which will be timed-out.

    import asyncio
    import socket

    ADDR = ('10.0.2.1', 22)


    async def check(loop):
        s = socket.socket(socket.AF_INET,
                        socket.SOCK_STREAM)
        s.setblocking(False)
        with s:
            await loop.sock_connect(s, ADDR)


    async def test(loop):
        try:
            await asyncio.wait_for(
                check(loop),
                timeout=3,
                loop=loop,
            )
        except Exception as e:
            print('Fail: %s' % e)
        else:
            print('Success')


    if __name__ == '__main__':
        loop = asyncio.get_event_loop()
        loop.run_until_complete(test(loop))
msg323238 - (view) Author: Alisue Lambda (Alisue Lambda) Date: 2018-08-07 09:24
I use the following patch to fix the behavior in Windows.


```
import sys

if sys.platform != 'win32':
    def patch():
        pass
else:
    def patch():
        """Patch selectors.SelectSelector to fix WinError 10038 in Windows

        Ref: https://bugs.python.org/issue33350
        """

        import select
        from selectors import SelectSelector

        def _select(self, r, w, _, timeout=None):
            try:
                r, w, x = select.select(r, w, w, timeout)
            except OSError as e:
                if hasattr(e, 'winerror') and e.winerror == 10038:
                    # descriptors may already be closed
                    return [], [], []
                raise
            else:
                return r, w + x, []

        SelectSelector._select = _select
```
History
Date User Action Args
2018-08-07 09:24:40Alisue Lambdasetmessages: + msg323238
2018-04-24 17:21:25Alisue Lambdasetmessages: + msg315709
2018-04-24 16:55:16Alisue Lambdasetmessages: + msg315708
2018-04-24 16:51:15Alisue Lambdacreate