Issues / #2432

#2432 Server deadlocks when the console window is paused (QuickEdit selection): the finish path prints the done line while holding status_lock

open · @anwang888 · 0 comentarios · En GitHub

BenchmarksServer & APINVIDIA / CUDAModels & quantsWindows

Descripción

## Summary

On Windows, selecting text in the server's console window (QuickEdit) pauses the console — and that permanently deadlocks the server: the per-request finish path prints the `[strata] done:` line **while holding `status_lock`**, so the print blocks forever holding the lock, and every later request hangs on `status_lock` (in `_progress` / `_note`). The engine itself stays alive and healthy. Reproduced 3 times in real use on 0.1.43.1 (both IQ3_S and Unsloth UD-IQ4_XS); the same structure exists in 0.1.42 and 0.1.43.

## Root cause

`serve/server.py`, the request-finish `finally` block (line numbers for 0.1.43.1; the same shape in 0.1.43 at 4029–4084 and 0.1.42 at 3935–3990):

```python
finally:
    with self.status_lock:          # :4169
        ... ~50 lines of stats settlement ...
        print(f"[strata] done: {n} tokens in {el:.0f} s ({rate:.1f} tok/s) "
              f"({finish}, cancel={cancel.is_set()}){hit_msg}", flush=True)   # :4224 — inside the lock
```

When the console is paused (QuickEdit selection), `print()` blocks in `WriteConsole` while the lock is held. Three more `print()` calls sit inside this same `with` block (repeated-reasoning, max-tokens-while-thinking, etc.).

`_progress()` takes the same lock (`with self.status_lock:` at :3798), so the next request's first progress line parks there forever. `/v1/status` shows the request `in_flight`; the engine log's last line is the engine-side stats — **the `[strata] done:` line is missing**, which is the blocked print itself.

## Reproduction (100%)

1. Windows, start the model with the stock `run-<model>.bat` (a console window).
2. Select any text in that console window with the mouse (QuickEdit) — e.g. to copy a log line. Do not press Esc.
3. Send any chat request. The engine completes it (the engine's own stats line appears in the log), but the HTTP response never arrives.
4. Every later request hangs too: py-spy shows request threads parked at `_progress (serve/server.py:3798)` (`with self.status_lock:`), double-sampled 12 s apart, identical; no thread in the process is inside `status_lock` at that point (the holder is the finish thread, blocked in the console write).
5. Control experiment: the same server with stdout redirected to a file (no console) never hangs — same requests complete in ~2 s, `done:` lines print normally. A console-window run hangs again on the next selection.

Pressing Esc/Enter in the window should release the console and let the print finish (not tested here; we always restarted, which also recovers).

## Suggested fix

Compute the `done` message inside the lock if needed, but move every `print()` in the finish path **outside** the `with self.status_lock:` block. The same applies to the other lock-held prints found in the finish/unload/error paths (`_progress` itself already prints outside its lock, which is the right pattern).

A wrapper that disables `ENABLE_QUICK_EDIT_MODE` at startup also mitigates it for anyone running the stock `.bat` files, but redirecting-vs-console is user-visible only after the fact — moving the prints out of the lock is the real fix.

## Environment

- Strata 0.1.43.1, engine self-built for sm_80 (CMP 170HX 64 GB), Windows 10 19045
- Quantizations: ISTA-DASLab IQ3_S and Unsloth UD-IQ4_XS — both reproduce; quantization is irrelevant
- Serving coding-agent sessions over the local API (`/v1/messages` and `/v1/chat/completions`)

Happy to attach py-spy dumps or the exact log excerpts if useful.

En el sitio

Enlaces a install, modelos, releases.