diff options
author | Junio C Hamano <gitster@pobox.com> | 2016-04-29 12:59:08 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2016-04-29 12:59:08 -0700 |
commit | d689301043f6dc14d71e7d33e1b8ea600ae1b67b (patch) | |
tree | de02603666c3fee3c3c1f93b826c27d020d40f1c | |
parent | 60b3e9b959f4423f6927ef77e7097bea3ad24e45 (diff) | |
parent | c4b27511ab0e3ec464e3fd3d4711251a17b1f733 (diff) | |
download | git-d689301043f6dc14d71e7d33e1b8ea600ae1b67b.tar.gz git-d689301043f6dc14d71e7d33e1b8ea600ae1b67b.tar.xz |
Merge branch 'jk/push-client-deadlock-fix'
"git push" from a corrupt repository that attempts to push a large
number of refs deadlocked; the thread to relay rejection notices
for these ref updates blocked on writing them to the main thread,
after the main thread at the receiving end notices that the push
failed and decides not to read these notices and return a failure.
* jk/push-client-deadlock-fix:
t5504: drop sigpipe=ok from push tests
fetch-pack: isolate sigpipe in demuxer thread
send-pack: isolate sigpipe in demuxer thread
run-command: teach async threads to ignore SIGPIPE
send-pack: close demux pipe before finishing async process
-rw-r--r-- | fetch-pack.c | 4 | ||||
-rw-r--r-- | run-command.c | 10 | ||||
-rw-r--r-- | run-command.h | 1 | ||||
-rw-r--r-- | send-pack.c | 7 | ||||
-rwxr-xr-x | t/t5504-fetch-receive-strict.sh | 10 |
5 files changed, 21 insertions, 11 deletions
diff --git a/fetch-pack.c b/fetch-pack.c index f96f6dfb3..b501d5c32 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -15,7 +15,6 @@ #include "version.h" #include "prio-queue.h" #include "sha1-array.h" -#include "sigchain.h" static int transfer_unpack_limit = -1; static int fetch_unpack_limit = -1; @@ -674,10 +673,8 @@ static int sideband_demux(int in, int out, void *data) int *xd = data; int ret; - sigchain_push(SIGPIPE, SIG_IGN); ret = recv_sideband("fetch-pack", xd[0], out); close(out); - sigchain_pop(SIGPIPE); return ret; } @@ -701,6 +698,7 @@ static int get_pack(struct fetch_pack_args *args, demux.proc = sideband_demux; demux.data = xd; demux.out = -1; + demux.isolate_sigpipe = 1; if (start_async(&demux)) die("fetch-pack: unable to fork off sideband" " demultiplexer"); diff --git a/run-command.c b/run-command.c index 8c7115ade..e4593cd99 100644 --- a/run-command.c +++ b/run-command.c @@ -590,6 +590,16 @@ static void *run_thread(void *data) struct async *async = data; intptr_t ret; + if (async->isolate_sigpipe) { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGPIPE); + if (pthread_sigmask(SIG_BLOCK, &mask, NULL) < 0) { + ret = error("unable to block SIGPIPE in async thread"); + return (void *)ret; + } + } + pthread_setspecific(async_key, async); ret = async->proc(async->proc_in, async->proc_out, async->data); return (void *)ret; diff --git a/run-command.h b/run-command.h index de1727efa..11f76b04e 100644 --- a/run-command.h +++ b/run-command.h @@ -116,6 +116,7 @@ struct async { int proc_in; int proc_out; #endif + int isolate_sigpipe; }; int start_async(struct async *async); diff --git a/send-pack.c b/send-pack.c index 047bd18fd..37ee04ea3 100644 --- a/send-pack.c +++ b/send-pack.c @@ -518,6 +518,7 @@ int send_pack(struct send_pack_args *args, demux.proc = sideband_demux; demux.data = fd; demux.out = -1; + demux.isolate_sigpipe = 1; if (start_async(&demux)) die("send-pack: unable to fork off sideband demultiplexer"); in = demux.out; @@ -531,8 +532,10 @@ int send_pack(struct send_pack_args *args, close(out); if (git_connection_is_socket(conn)) shutdown(fd[0], SHUT_WR); - if (use_sideband) + if (use_sideband) { + close(demux.out); finish_async(&demux); + } fd[1] = -1; return -1; } @@ -551,11 +554,11 @@ int send_pack(struct send_pack_args *args, packet_flush(out); if (use_sideband && cmds_sent) { + close(demux.out); if (finish_async(&demux)) { error("error in sideband demultiplexer"); ret = -1; } - close(demux.out); } if (ret < 0) diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index a3e12d295..44f3d5fb2 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -100,11 +100,8 @@ test_expect_success 'push with receive.fsckobjects' ' git config receive.fsckobjects true && git config transfer.fsckobjects false ) && - test_must_fail ok=sigpipe git push --porcelain dst master:refs/heads/test >act && - { - test_cmp exp act || - ! test -s act - } + test_must_fail git push --porcelain dst master:refs/heads/test >act && + test_cmp exp act ' test_expect_success 'push with transfer.fsckobjects' ' @@ -114,7 +111,8 @@ test_expect_success 'push with transfer.fsckobjects' ' cd dst && git config transfer.fsckobjects true ) && - test_must_fail ok=sigpipe git push --porcelain dst master:refs/heads/test >act + test_must_fail git push --porcelain dst master:refs/heads/test >act && + test_cmp exp act ' cat >bogus-commit <<\EOF |