Skip to content

Commit 44d8dc5

Browse files
committed
Fix potential local deadlock during fetch-pack
The fetch-pack/upload-pack protocol relies on the underlying transport (local pipe or TCP socket) to have enough slack to allow one window worth of data in flight without blocking the writer. Traditionally we always relied on being able to have two windows of 32 "have"s in flight (roughly 3k bytes) to stream. The recent "progressive-stride" change allows "fetch-pack" to send up to 1024 "have"s without reading any response from "upload-pack". The outgoing pipe of "upload-pack" can be clogged with many ACK and NAK that are unread, while "fetch-pack" is still stuffing its outgoing pipe with more "have"s, leading to a deadlock. Revert the change unless we are in stateless rpc (aka smart-http) mode, as using a large window full of "have"s is still a good way to help reduce the number of back-and-forth, and there is no buffering issue there (it is strictly "ping-pong" without an overlap). Signed-off-by: Junio C Hamano <[email protected]>
1 parent 066bf4c commit 44d8dc5

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

builtin/fetch-pack.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,17 @@ static void send_request(int fd, struct strbuf *buf)
219219
}
220220

221221
#define INITIAL_FLUSH 16
222+
#define PIPESAFE_FLUSH 32
222223
#define LARGE_FLUSH 1024
223224

224225
static int next_flush(int count)
225226
{
226-
if (count < INITIAL_FLUSH * 2)
227-
count += INITIAL_FLUSH;
228-
else if (count < LARGE_FLUSH)
227+
int flush_limit = args.stateless_rpc ? LARGE_FLUSH : PIPESAFE_FLUSH;
228+
229+
if (count < flush_limit)
229230
count <<= 1;
230231
else
231-
count += LARGE_FLUSH;
232+
count += flush_limit;
232233
return count;
233234
}
234235

0 commit comments

Comments
 (0)