diff --git a/src/dstack/_internal/cli/commands/server.py b/src/dstack/_internal/cli/commands/server.py index 255f92e9a5..3769d9b77d 100644 --- a/src/dstack/_internal/cli/commands/server.py +++ b/src/dstack/_internal/cli/commands/server.py @@ -103,6 +103,8 @@ def _command(self, args: argparse.Namespace): reload_excludes=reload_excludes, log_level=uvicorn_log_level, workers=1, + # uvloop spawns subprocesses with fork(), which can hang the server (#4362). + loop="asyncio", ) def _configure_logging(self) -> None: diff --git a/src/tests/_internal/cli/commands/test_server.py b/src/tests/_internal/cli/commands/test_server.py new file mode 100644 index 0000000000..5b8b4d0e9c --- /dev/null +++ b/src/tests/_internal/cli/commands/test_server.py @@ -0,0 +1,12 @@ +import os +from unittest.mock import patch + +from dstack._internal.cli.commands import server +from tests._internal.cli.common import run_dstack_cli + + +class TestServerCommand: + def test_runs_uvicorn_on_asyncio_loop(self): + with patch.dict(os.environ), patch.object(server.uvicorn, "run") as uvicorn_run: + assert run_dstack_cli(["server"]) == 0 + assert uvicorn_run.call_args.kwargs["loop"] == "asyncio"