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
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 #define sigemptyset(x) (void)0
static inline int sigaddset(sigset_t *set, int signum) static inline int sigaddset(sigset_t *set, int signum)
{ return 0; } { return 0; }
#define SIG_BLOCK 0
#define SIG_UNBLOCK 0 #define SIG_UNBLOCK 0
static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) static inline int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{ return 0; } { return 0; }

View File

@ -104,4 +104,11 @@ static inline void *pthread_getspecific(pthread_key_t key)
return TlsGetValue(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 */ #endif /* PTHREAD_H */

View File

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

View File

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

View File

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

View File

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

View File

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