antirez / antirez/ds4

client disconnect mid-generation not detected on clean TCP FIN (Darwin poll bug)

Ouverte
#786 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
Langage dominant
C
Étoiles
22.3k
Forks
2.1k
Merge moyen
1 j 3 h
PR mergées (30 j)
4

Description

### Bug: client disconnect mid-generation is not detected on a clean TCP FIN (Darwin)

ds4 was originally a macOS-first project (Metal backend), so this Darwin-specific
failure in the server's disconnect handling is the most common platform for it.

The disconnect cancel added in e9ded97 polls the client socket every 100ms from
`wait_for_job_or_disconnect` → `client_socket_disconnected()`, but **Darwin's
`poll()` does not report a plain TCP FIN**: no POLLIN, no POLLHUP — the call
returns 0 (no events). A client that closes the connection cleanly mid-generation
is therefore never seen.

#### Impact

- The job keeps decoding into a dead socket until `max_tokens` — on an M5 Max
that is ~12s of GPU time per disconnect, wasted.
- Only an RST trips cancellation (e.g. `close()` with unread receive data, or a
send failure), and that path returns silently: the `job_cancelled` early
returns in `generate_job_inner` skip the response path where the
"client disconnected" log lives, so cancelled work is invisible in the log.

#### Why the existing test misses it

`test_waiting_job_cancels_on_client_close` uses a socketpair and writes
pipelined data before closing. That makes `poll()` report POLLIN; `recv()` then
hits EOF, so the test passes — a clean FIN with no trailing data never
produces that event on Darwin.

#### Repro

Start the server, send a streaming request with `max_tokens=512`, close the
connection with `shutdown(SHUT_WR)` after a few SSE chunks (no RST). The log
shows all 512 tokens generated (`finish=length`) and never a
"client disconnected" line. Same for non-streaming requests closed
mid-generation.

#### Fix

PR #785 proposes `recv(MSG_PEEK)` probing after an eventless poll (reports EOF
exactly on every platform, consumes nothing, race-free with the worker's SSE
writes on the same fd), plus surfacing the cancellation at the seven early-return
sites. Verified live on M5 Max/Metal: detection in ~0.5s, job stops at
prefill/early decode, server stays healthy.

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.