Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

--reload flag gives me an OSError on Windows #477

Closed
Celeborn2BeAlive opened this issue Nov 5, 2019 · 11 comments
Closed

--reload flag gives me an OSError on Windows #477

Celeborn2BeAlive opened this issue Nov 5, 2019 · 11 comments

Comments

@Celeborn2BeAlive
Copy link

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 👍

@tomchristie
Copy link
Member

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?

@tomchristie
Copy link
Member

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.

@Celeborn2BeAlive
Copy link
Author

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: <asyncio.TransportSocket fd=800, 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.

@tomchristie
Copy link
Member

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... tornadoweb/tornado#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...

self.config.configure_logging()

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

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

@Celeborn2BeAlive
Copy link
Author

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.

@tomchristie
Copy link
Member

tomchristie commented Nov 6, 2019

"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.

@Celeborn2BeAlive
Copy link
Author

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\Lib\asyncio\base_events.py", line 555, in run_until_complete
self.run_forever()
File "c:\python37\Lib\asyncio\base_events.py", line 523, in run_forever
self._run_once()
File "c:\python37\Lib\asyncio\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’un 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.

@tomchristie
Copy link
Member

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

@tomchristie
Copy link
Member

Thanks for bringing this up!

@BramVanroy
Copy link

BramVanroy commented Nov 30, 2019

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.)

@tomchristie
Copy link
Member

tomchristie commented Dec 3, 2019

"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...

if sys.platform == "win32":

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants