aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2016-01-12 18:41:58 +0200
committerEli Zaretskii2016-01-12 18:41:58 +0200
commit58a622d473112f8ff5b4bdb3e49bc6573dfd3404 (patch)
tree58b618f654cae22d1e5f102cbb48bec56e833d45 /src
parent1f6898d0510cd15455f665c0f38451755a374243 (diff)
downloademacs-58a622d473112f8ff5b4bdb3e49bc6573dfd3404.tar.gz
emacs-58a622d473112f8ff5b4bdb3e49bc6573dfd3404.zip
Make piping to subprocesses more robust on MS-Windows
* src/w32.c (sys_write): Don't write to a pipe more stuff than its buffer can hold. Don't return -1 if something has been written to the pipe. Zero out 'errno' before calling '_write', to avoid returning a stale value. (Bug#22344) * src/w32proc.c (syms_of_ntproc) <w32-pipe-buffer-size>: New variable. * src/w32.c (pipe2): Use it to request a user-defined size for the pipe being created. * etc/NEWS: Mention 'w32-pipe-buffer-size'. * doc/emacs/msdos.texi (Windows Processes): Document 'w32-pipe-buffer-size'.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c39
-rw-r--r--src/w32proc.c7
2 files changed, 38 insertions, 8 deletions
diff --git a/src/w32.c b/src/w32.c
index 4770718f5e3..ea3a9dafad5 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -8043,14 +8043,19 @@ pipe2 (int * phandles, int pipe2_flags)
8043{ 8043{
8044 int rc; 8044 int rc;
8045 unsigned flags; 8045 unsigned flags;
8046 unsigned pipe_size = 0;
8046 8047
8047 eassert (pipe2_flags == (O_BINARY | O_CLOEXEC)); 8048 eassert (pipe2_flags == (O_BINARY | O_CLOEXEC));
8048 8049
8050 /* Allow Lisp to override the default buffer size of the pipe. */
8051 if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX)
8052 pipe_size = w32_pipe_buffer_size;
8053
8049 /* make pipe handles non-inheritable; when we spawn a child, we 8054 /* make pipe handles non-inheritable; when we spawn a child, we
8050 replace the relevant handle with an inheritable one. Also put 8055 replace the relevant handle with an inheritable one. Also put
8051 pipes into binary mode; we will do text mode translation ourselves 8056 pipes into binary mode; we will do text mode translation ourselves
8052 if required. */ 8057 if required. */
8053 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY); 8058 rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY);
8054 8059
8055 if (rc == 0) 8060 if (rc == 0)
8056 { 8061 {
@@ -8632,15 +8637,35 @@ sys_write (int fd, const void * buffer, unsigned int count)
8632 http://thread.gmane.org/gmane.comp.version-control.git/145294 8637 http://thread.gmane.org/gmane.comp.version-control.git/145294
8633 in the git mailing list. */ 8638 in the git mailing list. */
8634 const unsigned char *p = buffer; 8639 const unsigned char *p = buffer;
8635 const unsigned chunk = 30 * 1024 * 1024; 8640 const bool is_pipe = (fd < MAXDESC
8641 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
8642 == (FILE_PIPE | FILE_NDELAY)));
8643 /* Some programs, notably Node.js's node.exe, seem to never
8644 completely empty the pipe, so writing more than the size of
8645 the pipe's buffer always returns ENOSPC, and we loop forever
8646 between send_process and here. As a workaround, write no
8647 more than the pipe's buffer can hold. */
8648 DWORD pipe_buffer_size;
8649 if (is_pipe)
8650 {
8651 if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd),
8652 NULL, &pipe_buffer_size, NULL, NULL))
8653 {
8654 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8655 pipe_buffer_size = 4096;
8656 }
8657 }
8658 const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024;
8636 8659
8637 nchars = 0; 8660 nchars = 0;
8661 errno = 0;
8638 while (count > 0) 8662 while (count > 0)
8639 { 8663 {
8640 unsigned this_chunk = count < chunk ? count : chunk; 8664 unsigned this_chunk = count < chunk ? count : chunk;
8641 int n = _write (fd, p, this_chunk); 8665 int n = _write (fd, p, this_chunk);
8642 8666
8643 nchars += n; 8667 if (n > 0)
8668 nchars += n;
8644 if (n < 0) 8669 if (n < 0)
8645 { 8670 {
8646 /* When there's no buffer space in a pipe that is in the 8671 /* When there's no buffer space in a pipe that is in the
@@ -8654,12 +8679,10 @@ sys_write (int fd, const void * buffer, unsigned int count)
8654 avoiding deadlock whereby each side of the pipe is 8679 avoiding deadlock whereby each side of the pipe is
8655 blocked on write, waiting for the other party to read 8680 blocked on write, waiting for the other party to read
8656 its end of the pipe. */ 8681 its end of the pipe. */
8657 if (errno == ENOSPC 8682 if (errno == ENOSPC && is_pipe)
8658 && fd < MAXDESC
8659 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
8660 == (FILE_PIPE | FILE_NDELAY)))
8661 errno = EAGAIN; 8683 errno = EAGAIN;
8662 nchars = n; 8684 if (nchars == 0)
8685 nchars = -1;
8663 break; 8686 break;
8664 } 8687 }
8665 else if (n < this_chunk) 8688 else if (n < this_chunk)
diff --git a/src/w32proc.c b/src/w32proc.c
index a65f085fb3d..a89a9850466 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -3702,6 +3702,13 @@ of time slices to wait (effectively boosting the priority of the child
3702process temporarily). A value of zero disables waiting entirely. */); 3702process temporarily). A value of zero disables waiting entirely. */);
3703 w32_pipe_read_delay = 50; 3703 w32_pipe_read_delay = 50;
3704 3704
3705 DEFVAR_INT ("w32-pipe-buffer-size", w32_pipe_buffer_size,
3706 doc: /* Size of buffer for pipes created to communicate with subprocesses.
3707The size is in bytes, and must be non-negative. The default is zero,
3708which lets the OS use its default size, usually 4KB (4096 bytes).
3709Any negative value means to use the default value of zero. */);
3710 w32_pipe_buffer_size = 0;
3711
3705 DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names, 3712 DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names,
3706 doc: /* Non-nil means convert all-upper case file names to lower case. 3713 doc: /* Non-nil means convert all-upper case file names to lower case.
3707This applies when performing completions and file name expansion. 3714This applies when performing completions and file name expansion.