Skip to content

Commit f4d3af1

Browse files
committed
Merge branch 'jk/push-deadlock-regression-fix' into maint
"git push" had a handful of codepaths that could lead to a deadlock when unexpected error happened, which has been fixed. * jk/push-deadlock-regression-fix: send-pack: report signal death of pack-objects send-pack: read "unpack" status even on pack-objects failure send-pack: improve unpack-status error messages send-pack: use skip_prefix for parsing unpack status send-pack: extract parsing of "unpack" response receive-pack: fix deadlock when we cannot create tmpdir
2 parents 296ab78 + d1a13d3 commit f4d3af1

File tree

2 files changed

+40
-11
lines changed

2 files changed

+40
-11
lines changed

builtin/receive-pack.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1664,8 +1664,11 @@ static const char *unpack(int err_fd, struct shallow_info *si)
16641664
}
16651665

16661666
tmp_objdir = tmp_objdir_create();
1667-
if (!tmp_objdir)
1667+
if (!tmp_objdir) {
1668+
if (err_fd > 0)
1669+
close(err_fd);
16681670
return "unable to create temporary object directory";
1671+
}
16691672
child.env = tmp_objdir_env(tmp_objdir);
16701673

16711674
/*

send-pack.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
7272
struct child_process po = CHILD_PROCESS_INIT;
7373
FILE *po_in;
7474
int i;
75+
int rc;
7576

7677
i = 4;
7778
if (args->use_thin_pack)
@@ -125,27 +126,44 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
125126
po.out = -1;
126127
}
127128

128-
if (finish_command(&po))
129+
rc = finish_command(&po);
130+
if (rc) {
131+
/*
132+
* For a normal non-zero exit, we assume pack-objects wrote
133+
* something useful to stderr. For death by signal, though,
134+
* we should mention it to the user. The exception is SIGPIPE
135+
* (141), because that's a normal occurence if the remote end
136+
* hangs up (and we'll report that by trying to read the unpack
137+
* status).
138+
*/
139+
if (rc > 128 && rc != 141)
140+
error("pack-objects died of signal %d", rc - 128);
129141
return -1;
142+
}
143+
return 0;
144+
}
145+
146+
static int receive_unpack_status(int in)
147+
{
148+
const char *line = packet_read_line(in, NULL);
149+
if (!skip_prefix(line, "unpack ", &line))
150+
return error(_("unable to parse remote unpack status: %s"), line);
151+
if (strcmp(line, "ok"))
152+
return error(_("remote unpack failed: %s"), line);
130153
return 0;
131154
}
132155

133156
static int receive_status(int in, struct ref *refs)
134157
{
135158
struct ref *hint;
136-
int ret = 0;
137-
char *line = packet_read_line(in, NULL);
138-
if (!starts_with(line, "unpack "))
139-
return error("did not receive remote status");
140-
if (strcmp(line, "unpack ok")) {
141-
error("unpack failed: %s", line + 7);
142-
ret = -1;
143-
}
159+
int ret;
160+
144161
hint = NULL;
162+
ret = receive_unpack_status(in);
145163
while (1) {
146164
char *refname;
147165
char *msg;
148-
line = packet_read_line(in, NULL);
166+
char *line = packet_read_line(in, NULL);
149167
if (!line)
150168
break;
151169
if (!starts_with(line, "ok ") && !starts_with(line, "ng ")) {
@@ -557,6 +575,14 @@ int send_pack(struct send_pack_args *args,
557575
close(out);
558576
if (git_connection_is_socket(conn))
559577
shutdown(fd[0], SHUT_WR);
578+
579+
/*
580+
* Do not even bother with the return value; we know we
581+
* are failing, and just want the error() side effects.
582+
*/
583+
if (status_report)
584+
receive_unpack_status(in);
585+
560586
if (use_sideband) {
561587
close(demux.out);
562588
finish_async(&demux);

0 commit comments

Comments
 (0)