uvicorn: Run uvicorn with multiple workers on Windows - WinError 87

Describe the bug Uvicorn doesn’t seem to be able to start with multiple workers.

Code snippet Starlette Hello World

import uvicorn as uvicorn
from starlette.applications import Starlette
from starlette.responses import JSONResponse

app = Starlette(debug=True)


@app.route('/')
async def homepage(request):
    return JSONResponse({'hello': 'world'})


if __name__ == '__main__':
    uvicorn.run(app, host='127.0.0.1', port=8000, workers=2)

Expected behavior

Uvicorn starts and is ready to serve with multiple workers.

Environment

Windows 10 Uvicorn: 0.6.1 Python: 3.7.2 Starlette: 0.11.4

Additional context

(venv) C:\Users\marodev\source\repos\StarletteHelloWorldVirtualEnvPy37>python main.py

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started parent process [35788]

Traceback (most recent call last):

  File "main.py", line 14, in <module>
    uvicorn.run(app, host='127.0.0.1', port=8000, workers=2)
	
  File "C:\Users\marodev\source\repos\StarletteHelloWorldVirtualEnvPy37\venv\lib\site-packages\uvicorn\main.py", line 274, in run
    supervisor.run(server.run, sockets=[socket])
	
  File "C:\Users\marodev\source\repos\StarletteHelloWorldVirtualEnvPy37\venv\lib\site-packages\uvicorn\supervisors\multiprocess.py", line 33, in run
    process.start()
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\process.py", line 112, in start
    self._popen = self._Popen(self)
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\context.py", line 223, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\context.py", line 322, in _Popen
    return Popen(process_obj)
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
    reduction.dump(process_obj, to_child)
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
	
AttributeError: Can't pickle local object 'request_response.<locals>.app'

(venv) C:\Users\marodev\source\repos\StarletteHelloWorldVirtualEnvPy37>Traceback (most recent call last):
  File "<string>", line 1, in <module>
  
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\spawn.py", line 99, in spawn_main
    new_handle = reduction.steal_handle(parent_pid, pipe_handle)
	
  File "C:\Users\marodev\AppData\Local\Programs\Python\Python37\lib\multiprocessing\reduction.py", line 82, in steal_handle
    _winapi.PROCESS_DUP_HANDLE, False, source_pid)
	
OSError: [WinError 87] The parameter is incorrect

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 38 (10 by maintainers)

Most upvoted comments

The same issue with Python 3.9.10 and uvicorn 0.17.6.

Upgrading Uvicorn to “0.18.1” solved for me!

I believe the issue is related to the Python sockets lib on Windows. Windows effectively deadlocks a port during Python’s initial socket configuration. So if you have multiple python threads or interpreters attempting to start listening to a socket at once, you’ll get a WinError.

The consensus seems to be to use sleep between each socket listener setup. This can also be used in conjunction with some sort of retry logic that catches WinError

@tomchristie Can you please provide an update?