Work around issues that git hangs when doing fetch or pull under various protocols under CYGWIN. Replace pipe() with a socket connection using a TCP/IP. Introduce a new function socket_pipe() in compat/socket_pipe.c Re-define the pipe() function into socket_pipe() for CYGWIN. (This redefinition does not work for MinGW, because here a socket can not be mixed with a file handle) Signed-off-by: Torsten Bögershausen <tboegi@xxxxxx> --- compat/socket_pipe.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++ config.mak.uname | 2 ++ git-compat-util.h | 4 ++++ 3 files changed, 74 insertions(+) create mode 100644 compat/socket_pipe.c diff --git a/compat/socket_pipe.c b/compat/socket_pipe.c new file mode 100644 index 0000000..eee43b5 --- /dev/null +++ b/compat/socket_pipe.c @@ -0,0 +1,68 @@ +#include "git-compat-util.h" + +int socket_pipe(int filedes[2]) +{ + int fd_listen, fd_rd; + int fd_wr = -1; + struct sockaddr_in sin; + socklen_t length; + struct linger linger; + int reuse_on = 1; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + fd_listen = socket(AF_INET, SOCK_STREAM, 0); + if (fd_listen == -1) + die_errno("pipe fd_listen socket"); + (void)setsockopt(fd_listen, SOL_SOCKET, SO_REUSEADDR, + (char*)&reuse_on, sizeof(reuse_on)); + if (bind(fd_listen, (struct sockaddr *)&sin, sizeof(sin))) + die_errno("pipe bind socket"); + + length = sizeof(sin); + if(getsockname(fd_listen, (struct sockaddr *)&sin, &length)) + die_errno("pipe getsockname"); + if (listen(fd_listen, SOMAXCONN)) + die_errno("pipe listen"); + fd_rd = socket(AF_INET, SOCK_STREAM, 0); + if (fd_rd == -1) + die_errno("pipe fd_rd socket"); + if (connect(fd_rd, (struct sockaddr *)&sin, sizeof(sin))) + die_errno("pipe connect"); + + length = sizeof(struct sockaddr); + if(getsockname(fd_rd, (struct sockaddr *)&sin, &length)) + die_errno("pipe getsockname"); + + while (fd_wr == -1) { + struct sockaddr_in sacc; + length = sizeof(sacc); + memset(&sacc, 0, sizeof(sacc)); + fd_wr = accept(fd_listen, (struct sockaddr *)&sacc, &length); + if(fd_wr == -1) + die_errno("pipe accept"); + if (sacc.sin_port != sin.sin_port) { + // Wrong connecting socket + close(fd_wr); + fd_wr = -1; + } + } + + close(fd_listen); + + linger.l_onoff = 1; + linger.l_linger = 5; + if (setsockopt(fd_wr, SOL_SOCKET, SO_LINGER, + (char*)&linger, sizeof(linger))) + die_errno("pipe socket linger"); + if (shutdown(fd_rd, SHUT_WR)) + die_errno("pipe socket shutdown fd_rd"); + if (shutdown(fd_wr, SHUT_RD)) + die_errno("pipe socket shutdown fd_wr"); + + filedes[0] = fd_rd; + filedes[1] = fd_wr; + return 0; +} diff --git a/config.mak.uname b/config.mak.uname index d78fd3d..66bf446 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -170,7 +170,9 @@ ifeq ($(uname_O),Cygwin) # Try commenting this out if you suspect MMAP is more efficient NO_MMAP = YesPlease X = .exe + BASIC_CFLAGS += -DGIT_USE_SOCKET_PIPE COMPAT_OBJS += compat/cygwin.o + COMPAT_OBJS += compat/socket_pipe.o UNRELIABLE_FSTAT = UnfortunatelyYes SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield endif diff --git a/git-compat-util.h b/git-compat-util.h index c1f8a47..88632ab 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -176,6 +176,10 @@ int get_st_mode_bits(const char *path, int *mode); #endif #endif +int socket_pipe(int filedes[2]); +#ifdef GIT_USE_SOCKET_PIPE +#define pipe(a) socket_pipe(a) +#endif /* used on Mac OS X */ #ifdef PRECOMPOSE_UNICODE #include "compat/precompose_utf8.h" -- 1.8.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html