Uvicorn: [BUG] WinError 10022 when run on Windows with workers > 1

Created on 9 Dec 2019  路  12Comments  路  Source: encode/uvicorn

The error observed on Windows 10 with Python-3.6-amd64, Python-3.7-amd64, Python-3.8-amd64.
Sample app:

async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ]
    })
    await send({
        'type': 'http.response.body',
        'body': b'Uvicorn is the best!',
    })

OK when workers=1:

(venv) C:\Users\vasiliy.pankov\Projects\uvicorn-lab>uvicorn server:app
INFO:     Started server process [17728]
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     Shutting down
INFO:     Finished server process [17728]

WinError 10022 When workers > 1

(venv) C:\Users\vasiliy.pankov\Projects\uvicorn-lab>uvicorn --workers 2 server:app
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started parent process [13020]
INFO:     Started server process [6888]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     Started server process [19460]
Process SpawnProcess-1:
Traceback (most recent call last):
  File "C:\Python\Python38\lib\multiprocessing\process.py", line 313, in _bootstrap
    self.run()
  File "C:\Python\Python38\lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\subprocess.py", line 73, in subprocess_started
    target(sockets=sockets)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 341, in run
    loop.run_until_complete(self.serve(sockets=sockets))
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 608, in run_until_complete
    return future.result()
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 358, in serve
    await self.startup(sockets=sockets)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 386, in startup
    server = await loop.create_server(
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 1469, in create_server
    server._start_serving()
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 309, in _start_serving
    sock.listen(self._backlog)
OSError: [WinError 10022] An invalid argument was supplied
bug windows

Most helpful comment

+1 to fix from @euri10. Would be great to see this implemented.

All 12 comments

Could you confirm if this behaviour also replicates with --loop asyncio?

Incidentally you really don't need to be using multiple worker except in production.
A single worker will be perfectly capable of handling potentially 1000s of concurrent requests.

@tomchristie Yes I do.

(venv) PS C:\Users\vasiliy.pankov\Projects\uvicorn-lab> uvicorn --loop asyncio --workers 2 server:app
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started parent process [22292]
INFO:     Started server process [13844]
INFO:     Waiting for application startup.
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application startup complete.
INFO:     Started server process [19548]
Process SpawnProcess-2:
Traceback (most recent call last):
  File "C:\Python\Python38\lib\multiprocessing\process.py", line 313, in _bootstrap
    self.run()
  File "C:\Python\Python38\lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\subprocess.py", line 73, in subprocess_started
    target(sockets=sockets)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 341, in run
    loop.run_until_complete(self.serve(sockets=sockets))
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 608, in run_until_complete
    return future.result()
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 358, in serve
    await self.startup(sockets=sockets)
  File "c:\users\vasiliy.pankov\projects\uvicorn-lab\venv\lib\site-packages\uvicorn\main.py", line 386, in startup
    server = await loop.create_server(
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 1469, in create_server
    server._start_serving()
  File "C:\Python\Python38\lib\asyncio\base_events.py", line 309, in _start_serving
    sock.listen(self._backlog)
OSError: [WinError 10022] An invalid argument was supplied

The main reason why I want to have multiprocessing enabled is because I need to deploy Django app in production on Windows. Recently Django started to support ASGI. But it still remains synchronous. So the only way to make Django handle concurrent requests - use threads or multiprocessing. I am unable to use gunicorn on windows - it's only support UNIX. Another option - use Waitress, but it works only with threads. I think multiprocessing model is more reliable. So I decided to try new harness - Django + ASGI +uvicorn + multiprocessing but I failed :(

Add you're running 0.10.8?

@tomchristie Yes

PS C:\Users\vasiliy.pankov\Projects\uvicorn-lab> python -c "import uvicorn; print(uvicorn.__version__)"
0.10.8

I'm not sure what to do here. It's awkward since I'm unable to test this.

We are explicitly dealing with the windows multiprocessing case, where we need to marshall the sockets into DupSocket instances, in order to share them cross-process...

https://github.com/encode/uvicorn/blob/abd4b006c8a443bc80201409187ab3a662ac7c7e/uvicorn/subprocess.py#L36

And then restore them in the child process...

https://github.com/encode/uvicorn/blob/abd4b006c8a443bc80201409187ab3a662ac7c7e/uvicorn/subprocess.py#L66

It'd be useful to know if that portion of code is working as expected.

  • Are you able to print sockets in those two cases?
  • Are you able to confirm if everything works okay or not in the --reload case, when reloads occur?
  • Could you try import platform; print(platform.system()) ?
  • Are other windows users able to replicate this issue?

@tomchristie Thanks for hint! I will investigate this and tell you about the result.

I'm also seeing this issue and wanted to confirm that the PR from @euri10 fixes it for me.

have same issue when
uvicorn.run('test.asgi:application', workers=2, log_level='info')

interestingly if I run the script with PyCharm it works fine

Still having this same issue with python 3.7 and 3.8

uvicorn 0.11.5

uvicorn app.main:api --workers 2

Process SpawnProcess-2: Traceback (most recent call last): File "C:\Program Files\Python38\lib\multiprocessing\process.py", line 315, in _bootstrap self.run() File "C:\Program Files\Python38\lib\multiprocessing\process.py", line 108, in run self._target(*self._args, **self._kwargs) File "C:\Users\Zero\Documents\Packs\Python\proyectos\IPAX38Env\lib\site-packages\uvicorn\subprocess.py", line 62, in subprocess_started target(sockets=sockets) File "C:\Users\Zero\Documents\Packs\Python\proyectos\IPAX38Env\lib\site-packages\uvicorn\main.py", line 382, in run loop.run_until_complete(self.serve(sockets=sockets)) File "C:\Program Files\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete return future.result() File "C:\Users\Zero\Documents\Packs\Python\proyectos\IPAX38Env\lib\site-packages\uvicorn\main.py", line 399, in serve await self.startup(sockets=sockets) File "C:\Users\Zero\Documents\Packs\Python\proyectos\IPAX38Env\lib\site-packages\uvicorn\main.py", line 432, in startup server = await loop.create_server( File "C:\Program Files\Python38\lib\asyncio\base_events.py", line 1484, in create_server server._start_serving() File "C:\Program Files\Python38\lib\asyncio\base_events.py", line 313, in _start_serving sock.listen(self._backlog) OSError: [WinError 10022] An invalid argument was supplied

Tried fix created by @euri10 and works perfectly, i have been waiting for this a while with this at least we can use until is properly implemented, thank you all for this awesome work in uvicorn.

+1 to fix from @euri10. Would be great to see this implemented.

Also running into this issue on Win10 dev machine and Windows Server 2016 LTS docker container target.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

joshua-s picture joshua-s  路  5Comments

gnat picture gnat  路  6Comments

Gyllsdorff picture Gyllsdorff  路  6Comments

HenrikOssipoff picture HenrikOssipoff  路  5Comments

divad picture divad  路  6Comments