summaryrefslogtreecommitdiff
path: root/builtin/receive-pack.c
diff options
context:
space:
mode:
authorLibravatar Jiang Xin <worldhello.net@gmail.com>2020-11-11 19:32:01 +0800
committerLibravatar Junio C Hamano <gitster@pobox.com>2020-11-11 12:46:56 -0800
commitf65003b4c4abea49a00cc9f3d87b9f37db6b48f1 (patch)
tree9518439d6d8638d14588af6de29ed8490f4f7c42 /builtin/receive-pack.c
parentt5411: new helper filter_out_user_friendly_and_stable_output (diff)
downloadtgif-f65003b4c4abea49a00cc9f3d87b9f37db6b48f1.tar.xz
receive-pack: gently write messages to proc-receive
Johannes found a flaky hang in `t5411/test-0013-bad-protocol.sh` in the osx-clang job of the CI/PR builds, and ran into an issue when using the `--stress` option with the following error messages: fatal: unable to write flush packet: Broken pipe send-pack: unexpected disconnect while reading sideband packet fatal: the remote end hung up unexpectedly In this test case, the "proc-receive" hook sends an error message and dies earlier. While "receive-pack" on the other side of the pipe should forward the error message of the "proc-receive" hook to the client side, but it fails to do so. This is because "receive-pack" uses `packet_write_fmt()` and `packet_flush()` to write pkt-line message to "proc-receive" hook, and these functions die immediately when pipe is broken. Using "gently" forms for these functions will get more predicable output. Add more "--die-*" options to test helper to test different stages of the protocol between "receive-pack" and "proc-receive" hook. Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Jiang Xin <zhiyou.jx@alibaba-inc.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/receive-pack.c')
-rw-r--r--builtin/receive-pack.c87
1 files changed, 63 insertions, 24 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index bb9909c52e..2bd736525f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -977,15 +977,25 @@ static int read_proc_receive_report(struct packet_reader *reader,
int new_report = 0;
int code = 0;
int once = 0;
+ int response = 0;
for (;;) {
struct object_id old_oid, new_oid;
const char *head;
const char *refname;
char *p;
-
- if (packet_reader_read(reader) != PACKET_READ_NORMAL)
+ enum packet_read_status status;
+
+ status = packet_reader_read(reader);
+ if (status != PACKET_READ_NORMAL) {
+ /* Check whether proc-receive exited abnormally */
+ if (status == PACKET_READ_EOF && !response) {
+ strbuf_addstr(errmsg, "proc-receive exited abnormally");
+ return -1;
+ }
break;
+ }
+ response++;
head = reader->line;
p = strchr(head, ' ');
@@ -1145,28 +1155,41 @@ static int run_proc_receive_hook(struct command *commands,
if (use_push_options)
strbuf_addstr(&cap, " push-options");
if (cap.len) {
- packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
+ code = packet_write_fmt_gently(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
strbuf_release(&cap);
} else {
- packet_write_fmt(proc.in, "version=1\n");
+ code = packet_write_fmt_gently(proc.in, "version=1\n");
}
- packet_flush(proc.in);
+ if (!code)
+ code = packet_flush_gently(proc.in);
- for (;;) {
- int linelen;
+ if (!code)
+ for (;;) {
+ int linelen;
+ enum packet_read_status status;
- if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
- break;
+ status = packet_reader_read(&reader);
+ if (status != PACKET_READ_NORMAL) {
+ /* Check whether proc-receive exited abnormally */
+ if (status == PACKET_READ_EOF)
+ code = -1;
+ break;
+ }
- if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
- version = atoi(reader.line + 8);
- linelen = strlen(reader.line);
- if (linelen < reader.pktlen) {
- const char *feature_list = reader.line + linelen + 1;
- if (parse_feature_request(feature_list, "push-options"))
- hook_use_push_options = 1;
+ if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
+ version = atoi(reader.line + 8);
+ linelen = strlen(reader.line);
+ if (linelen < reader.pktlen) {
+ const char *feature_list = reader.line + linelen + 1;
+ if (parse_feature_request(feature_list, "push-options"))
+ hook_use_push_options = 1;
+ }
}
}
+
+ if (code) {
+ strbuf_addstr(&errmsg, "fail to negotiate version with proc-receive hook");
+ goto cleanup;
}
if (version != 1) {
@@ -1180,20 +1203,36 @@ static int run_proc_receive_hook(struct command *commands,
for (cmd = commands; cmd; cmd = cmd->next) {
if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string)
continue;
- packet_write_fmt(proc.in, "%s %s %s",
- oid_to_hex(&cmd->old_oid),
- oid_to_hex(&cmd->new_oid),
- cmd->ref_name);
+ code = packet_write_fmt_gently(proc.in, "%s %s %s",
+ oid_to_hex(&cmd->old_oid),
+ oid_to_hex(&cmd->new_oid),
+ cmd->ref_name);
+ if (code)
+ break;
+ }
+ if (!code)
+ code = packet_flush_gently(proc.in);
+ if (code) {
+ strbuf_addstr(&errmsg, "fail to write commands to proc-receive hook");
+ goto cleanup;
}
- packet_flush(proc.in);
/* Send push options */
if (hook_use_push_options) {
struct string_list_item *item;
- for_each_string_list_item(item, push_options)
- packet_write_fmt(proc.in, "%s", item->string);
- packet_flush(proc.in);
+ for_each_string_list_item(item, push_options) {
+ code = packet_write_fmt_gently(proc.in, "%s", item->string);
+ if (code)
+ break;
+ }
+ if (!code)
+ code = packet_flush_gently(proc.in);
+ if (code) {
+ strbuf_addstr(&errmsg,
+ "fail to write push-options to proc-receive hook");
+ goto cleanup;
+ }
}
/* Read result from proc-receive */