зеркало из https://github.com/microsoft/git.git
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:
Коммит
d689301043
|
@ -15,7 +15,6 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "prio-queue.h"
|
#include "prio-queue.h"
|
||||||
#include "sha1-array.h"
|
#include "sha1-array.h"
|
||||||
#include "sigchain.h"
|
|
||||||
|
|
||||||
static int transfer_unpack_limit = -1;
|
static int transfer_unpack_limit = -1;
|
||||||
static int fetch_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 *xd = data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sigchain_push(SIGPIPE, SIG_IGN);
|
|
||||||
ret = recv_sideband("fetch-pack", xd[0], out);
|
ret = recv_sideband("fetch-pack", xd[0], out);
|
||||||
close(out);
|
close(out);
|
||||||
sigchain_pop(SIGPIPE);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,6 +698,7 @@ static int get_pack(struct fetch_pack_args *args,
|
||||||
demux.proc = sideband_demux;
|
demux.proc = sideband_demux;
|
||||||
demux.data = xd;
|
demux.data = xd;
|
||||||
demux.out = -1;
|
demux.out = -1;
|
||||||
|
demux.isolate_sigpipe = 1;
|
||||||
if (start_async(&demux))
|
if (start_async(&demux))
|
||||||
die("fetch-pack: unable to fork off sideband"
|
die("fetch-pack: unable to fork off sideband"
|
||||||
" demultiplexer");
|
" demultiplexer");
|
||||||
|
|
|
@ -590,6 +590,16 @@ static void *run_thread(void *data)
|
||||||
struct async *async = data;
|
struct async *async = data;
|
||||||
intptr_t ret;
|
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);
|
pthread_setspecific(async_key, async);
|
||||||
ret = async->proc(async->proc_in, async->proc_out, async->data);
|
ret = async->proc(async->proc_in, async->proc_out, async->data);
|
||||||
return (void *)ret;
|
return (void *)ret;
|
||||||
|
|
|
@ -116,6 +116,7 @@ struct async {
|
||||||
int proc_in;
|
int proc_in;
|
||||||
int proc_out;
|
int proc_out;
|
||||||
#endif
|
#endif
|
||||||
|
int isolate_sigpipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
int start_async(struct async *async);
|
int start_async(struct async *async);
|
||||||
|
|
|
@ -518,6 +518,7 @@ int send_pack(struct send_pack_args *args,
|
||||||
demux.proc = sideband_demux;
|
demux.proc = sideband_demux;
|
||||||
demux.data = fd;
|
demux.data = fd;
|
||||||
demux.out = -1;
|
demux.out = -1;
|
||||||
|
demux.isolate_sigpipe = 1;
|
||||||
if (start_async(&demux))
|
if (start_async(&demux))
|
||||||
die("send-pack: unable to fork off sideband demultiplexer");
|
die("send-pack: unable to fork off sideband demultiplexer");
|
||||||
in = demux.out;
|
in = demux.out;
|
||||||
|
@ -531,8 +532,10 @@ int send_pack(struct send_pack_args *args,
|
||||||
close(out);
|
close(out);
|
||||||
if (git_connection_is_socket(conn))
|
if (git_connection_is_socket(conn))
|
||||||
shutdown(fd[0], SHUT_WR);
|
shutdown(fd[0], SHUT_WR);
|
||||||
if (use_sideband)
|
if (use_sideband) {
|
||||||
|
close(demux.out);
|
||||||
finish_async(&demux);
|
finish_async(&demux);
|
||||||
|
}
|
||||||
fd[1] = -1;
|
fd[1] = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -551,11 +554,11 @@ int send_pack(struct send_pack_args *args,
|
||||||
packet_flush(out);
|
packet_flush(out);
|
||||||
|
|
||||||
if (use_sideband && cmds_sent) {
|
if (use_sideband && cmds_sent) {
|
||||||
|
close(demux.out);
|
||||||
if (finish_async(&demux)) {
|
if (finish_async(&demux)) {
|
||||||
error("error in sideband demultiplexer");
|
error("error in sideband demultiplexer");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
close(demux.out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
@ -100,11 +100,8 @@ test_expect_success 'push with receive.fsckobjects' '
|
||||||
git config receive.fsckobjects true &&
|
git config receive.fsckobjects true &&
|
||||||
git config transfer.fsckobjects false
|
git config transfer.fsckobjects false
|
||||||
) &&
|
) &&
|
||||||
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
|
||||||
test_cmp exp act ||
|
|
||||||
! test -s act
|
|
||||||
}
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'push with transfer.fsckobjects' '
|
test_expect_success 'push with transfer.fsckobjects' '
|
||||||
|
@ -114,7 +111,8 @@ test_expect_success 'push with transfer.fsckobjects' '
|
||||||
cd dst &&
|
cd dst &&
|
||||||
git config transfer.fsckobjects true
|
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
|
cat >bogus-commit <<\EOF
|
||||||
|
|
Загрузка…
Ссылка в новой задаче