[PATCHv3 2/9] send-pack: Attempt to retrieve remote status even if pack-objects fails
- From
Johan Herland <johan@herland.net>
- Date
- May 15, 2011, 21:37 UTC
- Message-ID
- <1305495440-30836-3-git-send-email-johan@herland.net>
- In-Reply-To
- <1305495440-30836-1-git-send-email-johan@herland.net>
When pushing, send-pack uses pack-objects to write the pack data to the receive-pack process running on the remote end. The scenarios where pack-objects dies unexpectedly, can be roughly divided based whether the reason for the failure is _local_ (i.e. something in pack-objects caused it to fail of its own accord), or _remote_ (i.e. something in the remote receive-pack process caused it to fail, leaving the local pack-objects process with a broken pipe)
If the reason for the failure is local, we expect pack-objects to report an appropriate error message to the user.
However, if the reason for the failure is remote, pack-objects will merely abort because of the broken pipe, and the user is left with no clue as to the reason why the remote receive-pack process died.
In certain cases, though, the receive-pack process on the other end may have produced an error message immediately before exiting. This error message may be currently waiting to be read by the local send-pack process.
Therefore, we should try to read from the remote end, even when pack-objects dies unexepectedly. We accomplish this by _always_ calling receive_status() after pack_objects(). If the remote end managed to produce a well-formed status report before exiting, then receive_status() simply presents that to the user. Even if the data from the remote end cannot be understood by receive_status(), it will print that data as part of its error message. In any case, we give the user as much information about the failure as possible.
Signed-off-by: Johan Herland <johan@herland.net> ---
I first wrote this patch on a base where e07fd15 (Peff's "send-pack: unbreak push over stateless rpc") was not present, and then resolved a conflict when rebasing this patch onto current master. I hope Peff or Johannes (Sixt) can verify that my patch does not reintroduce the deadlock they fixed.
...Johan
builtin/send-pack.c | 18 +++++------------- 1 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/builtin/send-pack.c b/builtin/send-pack.c index 4ac2ca9..f571917 100644 --- a/builtin/send-pack.c +++ b/builtin/send-pack.c @@ -251,7 +251,7 @@ int send_pack(struct send_pack_args *args, int status_report = 0; int use_sideband = 0; unsigned cmds_sent = 0; - int ret; + int ret = 0; struct async demux; /* Does the other end support the reporting? */ @@ -339,23 +339,15 @@ int send_pack(struct send_pack_args *args, } if (new_refs && cmds_sent) { - if (pack_objects(out, remote_refs, extra_have, args) < 0) { - for (ref = remote_refs; ref; ref = ref->next) - ref->status = REF_STATUS_NONE; - if (args->stateless_rpc) - close(out); - if (use_sideband) - finish_async(&demux); - return -1; - } + ret = pack_objects(out, remote_refs, extra_have, args); + if (ret && args->stateless_rpc) + close(out); } if (args->stateless_rpc && cmds_sent) packet_flush(out); if (status_report && cmds_sent) - ret = receive_status(in, remote_refs); - else - ret = 0; + ret |= receive_status(in, remote_refs); if (args->stateless_rpc) packet_flush(out);
-- 1.7.5.rc1.3.g4d7b