Skip to content

Commit e07fd15

Browse files
peffgitster
authored andcommitted
send-pack: unbreak push over stateless rpc
Commit 09c9957 (send-pack: avoid deadlock when pack-object dies early, 2011-04-25) attempted to fix a hang in the stateless rpc case by closing a file descriptor early, but we still need that descriptor. Basically the deadlock can happen when pack-objects fails, and the descriptor to upstream is left open. We never send the pack, so the upstream is left waiting for us to say something, and we are left waiting for upstream to close the connection. In the non-rpc case, our descriptor points straight to the upstream. We hand it off to run-command, which takes ownership and closes the descriptor after pack-objects finishes (whether it succeeds or not). Commit 09c9957 tried to emulate that in the rpc case. That isn't right, though. We actually have a descriptor going back to the remote-helper, and we need to keep using it after pack-objects is finished. Closing it early completely breaks pushing via smart-http. We still need to do something on error to signal the remote-helper that we won't be sending any pack data (otherwise we get the deadlock). In an ideal world, we would send a special packet back that says "Sorry, there was an error". But the remote-helper doesn't understand any such packet, so the best we can do is close the descriptor and let it report that we hung up unexpectedly. Signed-off-by: Jeff King <[email protected]> Acked-by: Johannes Sixt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 09c9957 commit e07fd15

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

builtin-send-pack.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ static int pack_objects(int fd, struct ref *refs, struct extra_have_objects *ext
9797
free(buf);
9898
close(po.out);
9999
po.out = -1;
100-
close(fd);
101100
}
102101

103102
if (finish_command(&po))
@@ -519,6 +518,8 @@ int send_pack(struct send_pack_args *args,
519518
if (pack_objects(out, remote_refs, extra_have, args) < 0) {
520519
for (ref = remote_refs; ref; ref = ref->next)
521520
ref->status = REF_STATUS_NONE;
521+
if (args->stateless_rpc)
522+
close(out);
522523
if (use_sideband)
523524
finish_async(&demux);
524525
return -1;

0 commit comments

Comments
 (0)