1
0
mirror of https://github.com/git/git.git synced 2025-04-14 12:25:31 +00:00

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
This commit is contained in:
Junio C Hamano 2016-04-29 12:59:08 -07:00
commit d689301043
5 changed files with 21 additions and 11 deletions

@ -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");

@ -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;

@ -116,6 +116,7 @@ struct async {
int proc_in;
int proc_out;
#endif
int isolate_sigpipe;
};
int start_async(struct async *async);

@ -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)

@ -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