Uvicorn: --reload flag gives me an OSError on Windows

Created on 5 Nov 2019  路  11Comments  路  Source: encode/uvicorn

Hi,
I'm trying a basic example with uvicorn : https://github.com/Celeborn2BeAlive/python_uvicorn_example
It's working but no the reload function: when I modify a file I get an OSError and the server seems to block when I refresh my page in my browser. After that I have to kill the server and start it again. Here is my complete output from uvicorn:

$ uvicorn.exe example:app --reload
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [18104]
INFO:     Started server process [8440]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     127.0.0.1:59375 - "GET / HTTP/1.1" 200
INFO:     127.0.0.1:59375 - "GET /favicon.ico HTTP/1.1" 200
WARNING:  Detected file change in 'example.py'. Reloading...
INFO:     Started server process [15148]
ERROR:    Accept failed on a socket
socket: <asyncio.TransportSocket fd=812, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 8000)>
Traceback (most recent call last):
  File "c:\python38\Lib\asyncio\proactor_events.py", line 817, in loop
    f = self._proactor.accept(sock)
  File "c:\python38\Lib\asyncio\windows_events.py", line 545, in accept
    self._register_with_iocp(listener)
  File "c:\python38\Lib\asyncio\windows_events.py", line 714, in _register_with_iocp
    _overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
OSError: [WinError 87] Param猫tre incorrect
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.

Here is some details about my system:

  • python 3.8.0
  • uvicorn 0.10.3 (installed from pip)
  • Windows 10 Professional x64 1903 18362.418

Note that I also tried with python 3.7.x and uvicorn 0.9.x and I had the same results.

Thanks for your work on uvicorn 馃憤

All 11 comments

Thanks for filing this report. I'm wondering if there's an issue with the IOCP event loop here.
Could you try the same again, using --loop asynio, and let me know if that works, and if not, what the traceback is?

One other issue that this throws up, is that we ought to be quiting when that error occurs, rather than continuing with application startup - it'd be worth us digging into that, too.

Thanks for your answer.

Unfortunately I get the same error with --loop asyncio:

$ uvicorn example:app --reload --loop asyncio
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [1648]
INFO: Started server process [33832]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
WARNING: Detected file change in 'example.py'. Reloading...
INFO: Started server process [28660]
ERROR: Accept failed on a socket
socket: Traceback (most recent call last):
File "c:\python38\Libasyncio\proactor_events.py", line 817, in loop
f = self._proactor.accept(sock)
File "c:\python38\Libasyncio\windows_events.py", line 545, in accept
self._register_with_iocp(listener)
File "c:\python38\Libasyncio\windows_events.py", line 714, in _register_with_iocp
_overlapped.CreateIoCompletionPort(obj.fileno(), self._iocp, 0, 0)
OSError: [WinError 87] Param猫tre incorrect
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.

Thanks.
Can you confirm if this occurs on initial startup, or only once the first reload occurs?

It's obviously related to Python 3.8.0 switching to IOCP as the default async loop implementation.
It looks like a bug in Python itself, since Uvicorn isn't even present in the stack trace anywhere there.

Related... https://github.com/tornadoweb/tornado/issues/2608

For one thing I think we might want to start by adding self.config.setup_event_loop() to the point at which we initialize the reloaded process... https://github.com/encode/uvicorn/blob/f846a3514d5c152f300f03b882c05aaf915e73cb/uvicorn/supervisors/statreload.py#L43

That's presumably fix things when --loop asyncio is being used.

We could then explicitly switch to asyncio being the default, perhaps.

The error occurs each time I modify the file and save it. I tried adding the self.config.setup_event_loop() just after the line you mention but it does not solve the issue.
Also note that I tried with 3.7 and I also had the problem. I can try with older versions of python if you want.

"I tried with 3.7 and I also had the problem"

Could you run it with Python 3.7 and --loop asyncio and paste the exact output?
Thanks for your time on this.

Amazing it works with Python 3.7 and --loop asyncio ! Probably not needed but here is the output:

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [22936]
INFO: Started server process [29388]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
INFO: 127.0.0.1:61320 - "GET / HTTP/1.1" 200
INFO: 127.0.0.1:61320 - "GET /favicon.ico HTTP/1.1" 200
WARNING: Detected file change in 'example.py'. Reloading...
INFO: Started server process [3888]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.

Thank you for the workaround, I will stick to python 3.7 for now.


However, unrelated but when I stop the server with CTRL+C I have this OSError:
INFO: Shutting down
Process SpawnProcess-1:
Traceback (most recent call last):
File "c:\python37\Lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "c:\python37\Lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, self._kwargs)
File "d:\developpement\python_examples\python_uvicorn_example\venv37\lib\site-packages\uvicorn\supervisors\statreload.py", line 44, in start_subprocess
target(
kwargs)
File "d:\developpement\python_examples\python_uvicorn_example\venv37\lib\site-packages\uvicorn\main.py", line 338, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "c:\python37\Libasyncio\base_events.py", line 555, in run_until_complete
self.run_forever()
File "c:\python37\Libasyncio\base_events.py", line 523, in run_forever
self._run_once()
File "c:\python37\Libasyncio\base_events.py", line 1722, in _run_once
event_list = self._selector.select(timeout)
File "c:\python37\Lib\selectors.py", line 323, in select
r, w, _ = self._select(self._readers, self._writers, [], timeout)
File "c:\python37\Lib\selectors.py", line 314, in _select
r, w, x = select.select(r, w, w, timeout)
OSError: [WinError 10038] Une op茅ration a 茅t茅 tent茅e sur autre chose qu鈥檜n socket
INFO: Stopping reloader process [29276]

It does not happen without --loop asyncio. It does not really hurt since it occurs at exist but I guess you want to keep things clean. If you want I can open another issue for this one just to keep track of it.

Should be closed via #487. Now released as 0.10.6.

Thanks for bringing this up!

Is it possible that this is _not_ fixed? I still experience this issue on 0.10.8 with Python 3.7 as well as 3.6. (The asyncio work-around does work, though.)

"The asyncio work-around does work, though"

Hrm. That's interesting. Could you open a fresh issue to track this, so we've got a cleaner history on the issue (there's a few bits and pieces mashed together on this one.)

I think we probably want to default to asyncio on all platforms at the moment, since the IOCP variant seems more flaky.

You'd be welcome to make a PR onto it as well if you fancy...

https://github.com/encode/uvicorn/blob/ad4ea90568a42eaa24cc6c597783246de5f35915/uvicorn/loops/auto.py#L8

This is where we're auto-selecting which event loop to use. We probably just want to get rid of the if sys.platform == "win32": branch entirely.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

divad picture divad  路  6Comments

ipmb picture ipmb  路  7Comments

yezyilomo picture yezyilomo  路  5Comments

vikahl picture vikahl  路  4Comments

tomchristie picture tomchristie  路  4Comments