`backpressure` stopped writing at the first WouldBlock. On macOS the
accepted stream does not keep the listener's 4 KiB receive buffer (it
gets about 114 KiB), so that WouldBlock only meant the 4 KiB send buffer
was full; it drained into the peer, and the 64 KiB write in
a_write_to_a_peer_that_stops_reading_fails_after_the_timeout and
a_blocked_socket_doesnt_hold_up_the_others_and_close_interrupts_it then
succeeded instead of blocking. Both tests failed on every run.
The helper now stops only after writes have stayed blocked for 200 ms,
still within its 16 MiB and 5 s limits. The socket code is unchanged.
Poison recovery, OsStr::to_str and char predicates only; S4325 casts are
f64 to f32 and stay.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Every socket operation locked one global table and held it through the
blocking write_all/flush, and streams had no write timeout (accepted
ones were explicitly blocking). A peer that stopped reading kept the
script blocked for good, and every other socket call, close included,
waited behind it.
- The table maps handles to Arc<Entry>, each with its own Mutex<Sock>.
The table is locked only to look a socket up, add or remove one,
never during network I/O, so one stalled socket doesn't hold up the
others.
- `write` sets a write timeout from the socket's `timeout` (10 s by
default, as reads) and reports "write timed out … the other side
isn't reading" instead of blocking. Failures to set the read or write
timeout, or to make an accepted stream blocking, are reported instead
of ignored.
- `close` removes the socket and shuts its stream down through a second
handle, so a call blocked on it fails at once.
Tests (socket.rs, native only): a 64 MB write to a loopback peer that
never reads fails with "timed out" after a 1 s timeout; while one socket
is blocked writing, another answers at once, and closing the blocked one
returns at once and ends its write. Both fail on main (the write never
gives up; the second socket waits on the table lock).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>