Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2022-09-13 22:21:08 +0300
committerJunio C Hamano <gitster@pobox.com>2022-09-13 22:21:08 +0300
commitaa31cb89743a9ba4efd43f5160bfea0a4cbe5858 (patch)
tree0c70668c1d69a88696f9e40c5bc4d90617170286 /compat
parent72869e750bf62fa313e7854d18e48c083f4720cc (diff)
parent716c1f649e372a0784b9826cd3839e7b373e2ea9 (diff)
Merge branch 'jk/pipe-command-nonblock' into maint
Fix deadlocks between main Git process and subprocess spawned via the pipe_command() API, that can kill "git add -p" that was reimplemented in C recently. * jk/pipe-command-nonblock: pipe_command(): mark stdin descriptor as non-blocking pipe_command(): handle ENOSPC when writing to a pipe pipe_command(): avoid xwrite() for writing to pipe git-compat-util: make MAX_IO_SIZE define globally available nonblock: support Windows compat: add function to enable nonblocking pipes
Diffstat (limited to 'compat')
-rw-r--r--compat/nonblock.c50
-rw-r--r--compat/nonblock.h9
2 files changed, 59 insertions, 0 deletions
diff --git a/compat/nonblock.c b/compat/nonblock.c
new file mode 100644
index 0000000000..9694ebdb1d
--- /dev/null
+++ b/compat/nonblock.c
@@ -0,0 +1,50 @@
+#include "git-compat-util.h"
+#include "nonblock.h"
+
+#ifdef O_NONBLOCK
+
+int enable_pipe_nonblock(int fd)
+{
+ int flags = fcntl(fd, F_GETFL);
+ if (flags < 0)
+ return -1;
+ flags |= O_NONBLOCK;
+ return fcntl(fd, F_SETFL, flags);
+}
+
+#elif defined(GIT_WINDOWS_NATIVE)
+
+#include "win32.h"
+
+int enable_pipe_nonblock(int fd)
+{
+ HANDLE h = (HANDLE)_get_osfhandle(fd);
+ DWORD mode;
+ DWORD type = GetFileType(h);
+ if (type == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR) {
+ errno = EBADF;
+ return -1;
+ }
+ if (type != FILE_TYPE_PIPE)
+ BUG("unsupported file type: %lu", type);
+ if (!GetNamedPipeHandleState(h, &mode, NULL, NULL, NULL, NULL, 0)) {
+ errno = err_win_to_posix(GetLastError());
+ return -1;
+ }
+ mode |= PIPE_NOWAIT;
+ if (!SetNamedPipeHandleState(h, &mode, NULL, NULL)) {
+ errno = err_win_to_posix(GetLastError());
+ return -1;
+ }
+ return 0;
+}
+
+#else
+
+int enable_pipe_nonblock(int fd)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+#endif
diff --git a/compat/nonblock.h b/compat/nonblock.h
new file mode 100644
index 0000000000..af1a331301
--- /dev/null
+++ b/compat/nonblock.h
@@ -0,0 +1,9 @@
+#ifndef COMPAT_NONBLOCK_H
+#define COMPAT_NONBLOCK_H
+
+/*
+ * Enable non-blocking I/O for the pipe specified by the passed-in descriptor.
+ */
+int enable_pipe_nonblock(int fd);
+
+#endif