Merge branch 'jk/push-client-deadlock-fix' into HEAD

Some Windows SDK lacks pthread_sigmask() implementation and fails
to compile the recently updated "git push" codepath that uses it.

* jk/push-client-deadlock-fix:
  Windows: only add a no-op pthread_sigmask() when needed
  Windows: add pthread_sigmask() that does nothing
  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-05-18 14:40:06 -07:00
commit c555e529ac
7 changed files with 29 additions and 11 deletions

View File

@ -142,6 +142,7 @@ static inline int fcntl(int fd, int cmd, ...)
#define sigemptyset(x) (void)0
static inline int sigaddset(sigset_t *set, int signum)
{ return 0; }
#define SIG_BLOCK 0
#define SIG_UNBLOCK 0
static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{ return 0; }

View File

@ -104,4 +104,11 @@ static inline void *pthread_getspecific(pthread_key_t key)
return TlsGetValue(key);
}
#ifndef __MINGW64_VERSION_MAJOR
static inline int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
{
return 0;
}
#endif
#endif /* PTHREAD_H */

View File

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

View File

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

View File

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

View File

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

View File

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