Fossil SCM
checkin/e4180437441b1f1c074bc11e587011441c358ed664b247202b933990bb130318
clone and sync often hang or appear to hang on links with highly variable latency, sometimes doing so many retries the transfer rate is infeasibly slow and at others spinning on reads that never complete. Both git and mercurial cope well with the same network doing very similar transfers, seemingly due to their protocol design and implementatin. The fixes here improve the fossil implementation somewhat. Everything here was tested with the fossil HTTP 1.1 patch.
- Set TCP_NODELAY on the client socket
The sync protocol interleaves small control writes with bulk transfer, and with the Nagle algorithm active those small writes are held waiting for ACKs; combined with the peer's delayed ACKs this throttles throughput badly on higher-latency paths. Disabling Nagle can give a 10x throughput improvement. This is what curl and many other HTTP clients do (Git uses curl.)
- No blocking forever on TLS reads and writes
After the TLS handshake the socket is switched to non-blocking mode. ssl_send() and ssl_receive() now wait for readiness with poll() and a timeout, and abandon a connection that has stopped communicating or been reset. The blocking socket remains during the handshake so behaviour is unchanged.
- Retry on EINTR
If a signal interrupts recv()/send() we now return -1/EINTR. This seems to be an improvement on treating the signal as end-of-stream and silently truncating the transfer.
- Report truncated replies as errors
When a read makes no progress due to a stalled or half-closed connection we now return NULL to indicate end of input. This means we no longer try to parse partial responses.