The pcntl_alarm backstop around pgsqlCopyFromArray was never a deadline: PHP
dispatches async signals only at VM opcode boundaries and libpq retries EINTR
internally, so a blocked call never yielded one. A stalled write was bounded
only by tcp_retries2 (~15 min), during which the buffer fills to
max_pending_rows and ingest starts refusing payloads outright. The deadline now
comes from the socket (tcp_user_timeout + keepalives, feature-detected because
libpq rejects an unknown keyword fatally), so it covers every statement on the
connection rather than the COPY call sites, and surfaces as a catchable
exception.
Also: lock_timeout on the drain transaction, SET LOCAL synchronous_commit so it
stops leaking onto pooled connections, HY000 classified as a connection error
so a stall reconnects instead of looping on a dead handle, and a DRAIN_WEDGED
diagnosis naming the blocking call.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>