Lightning-AI / Lightning-AI/LitServe

wrap_litserve_start() hangs on requests when worker setup() is slow

Open
#681 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug help wanted
Dominant language
Python
Stars
3.9k
Forks
304
Avg merge
3d 13h
Merged PRs (30d)
6

Description

🐛 Bug

wrap_litserve_start() is a pytest utility that starts the LitServe server in a context manager for testing. It launches inference worker processes but yields immediately without waiting for them to finish setup() (model loading, etc.).

This causes TestClient.post() to hang indefinitely because the worker hasn't started listening on the request queue yet. The request gets enqueued but never processed.

To Reproduce
import litserve as ls
from fastapi.testclient import TestClient


class SlowSetupAPI(ls.LitAPI):
    def setup(self, device):
        import time
        time.sleep(5)  # simulate slow model loading
        self.model = lambda x: x

    def decode_request(self, request):
        return request["input"]

    def predict(self, x):
        return self.model(x)

    def encode_response(self, output):
        return {"output": output}


def test_predict():
    api = SlowSetupAPI()
    server = ls.LitServer(api, accelerator="cpu")

    with ls.utils.wrap_litserve_start(server):
        client = TestClient(server.app)
        # This hangs forever because the worker is still in setup()
        response = client.post("/predict", json={"input": "hello"})

    assert response.status_code == 200
Code sample

The root cause is in litserve/utils.py. wrap_litserve_start calls launch_inference_worker() but never waits for workers_setup_status to reach READY, unlike LitServer.run() which has this loop:

# From server.py run() — this wait is missing from wrap_litserve_start
while not all(v == WorkerSetupStatus.READY for v in self.workers_setup_status.values()):
    if any(v == WorkerSetupStatus.ERROR for v in self.workers_setup_status.values()):
        raise RuntimeError("One or more workers failed to start. Shutting down LitServe")
    time.sleep(0.05)
Expected behavior

wrap_litserve_start should wait for all workers to be ready before yielding, matching the behavior of LitServer.run(). This would ensure TestClient requests are processed immediately without hanging.

Environment
  • LitServe Version: 0.2.17
  • OS: Linux
  • Python version: 3.12
  • How you installed: pip install litserve
Reproduction setup with uv
uv init --python 3.12
uv add "litserve==0.2.17" pytest pytest-timeout httpx
uv run pytest test_bug.py -v --timeout=30
Additional context

Related issues: #263 (setup not awaited), #663 (health check returns 200 when workers not ready), #660 (stale worker status).

Workaround:

import time

with ls.utils.wrap_litserve_start(server):
    while not all(v == "ready" for v in server.workers_setup_status.values()):
        time.sleep(0.5)
    with TestClient(server.app) as client:
        response = client.post("/predict", json={"input": "hello"})

Suggested fix: Add the worker readiness wait loop to wrap_litserve_start before yielding:

@contextmanager
def wrap_litserve_start(server: "LitServer", worker_monitor: bool = False):
    # ... existing setup code ...

    # Wait for all workers to be ready (same as LitServer.run)
    while not all(
        v == WorkerSetupStatus.READY for v in server.workers_setup_status.values()
    ):
        if any(v == WorkerSetupStatus.ERROR for v in server.workers_setup_status.values()):
            raise RuntimeError("One or more workers failed to start")
        time.sleep(0.05)

    try:
        yield server
    finally:
        # ... existing teardown code ...

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in litserve/utils.py and compare wrap_litserve_start with the readiness loop in server.py’s LitServer.run(). Reproduce the slow setup case with the provided uv and pytest commands, then verify that requests no longer hang and worker startup errors are handled before the context manager yields.

Written by the indexing model from the issue text.

Assessment

Tech stack
fastapi, python
Domain
backend, testing
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.