aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2016-01-12 18:41:58 +0200
committerEli Zaretskii2016-01-12 18:41:58 +0200
commit58a622d473112f8ff5b4bdb3e49bc6573dfd3404 (patch)
tree58b618f654cae22d1e5f102cbb48bec56e833d45
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'.
-rw-r--r--doc/emacs/msdos.texi14
-rw-r--r--etc/NEWS6
-rw-r--r--src/w32.c39
-rw-r--r--src/w32proc.c7
4 files changed, 56 insertions, 10 deletions
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index ea8a24d1cf7..6ad12d646a1 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -655,7 +655,7 @@ and the right button generates @kbd{mouse-3} events. If this variable
655is non-@code{nil}, the roles of these two buttons are reversed. 655is non-@code{nil}, the roles of these two buttons are reversed.
656 656
657@node Windows Processes 657@node Windows Processes
658@section Subprocesses on Windows 9X/ME and Windows NT/2K/XP 658@section Subprocesses on Windows 9X/ME and Windows NT/2K/XP/Vista/7/8/10
659@cindex subprocesses on MS-Windows 659@cindex subprocesses on MS-Windows
660 660
661@cindex DOS applications, running from Emacs 661@cindex DOS applications, running from Emacs
@@ -663,7 +663,8 @@ is non-@code{nil}, the roles of these two buttons are reversed.
663version) includes full support for asynchronous subprocesses. 663version) includes full support for asynchronous subprocesses.
664In the Windows version, synchronous and asynchronous subprocesses work 664In the Windows version, synchronous and asynchronous subprocesses work
665fine on both 665fine on both
666Windows 9X/ME and Windows NT/2K/XP as long as you run only 32-bit Windows 666Windows 9X/ME and Windows NT/2K/XP/Vista/7/8/10 as long as you run
667only 32-bit or 64-bit Windows
667applications. However, when you run a DOS application in a subprocess, 668applications. However, when you run a DOS application in a subprocess,
668you may encounter problems or be unable to run the application at all; 669you may encounter problems or be unable to run the application at all;
669and if you run two DOS applications at the same time in two 670and if you run two DOS applications at the same time in two
@@ -713,6 +714,15 @@ character. If the value is a character, Emacs uses that character to escape
713any quote characters that appear; otherwise it chooses a suitable escape 714any quote characters that appear; otherwise it chooses a suitable escape
714character based on the type of the program. 715character based on the type of the program.
715 716
717@vindex w32-pipe-buffer-size
718 The variable @code{w32-pipe-buffer-size} controls the size of the
719buffer Emacs requests from the system when it creates pipes for
720communications with subprocesses. The default value is zero, which
721lets the OS choose the size. Any valid positive value will request a
722buffer of that size in bytes. This can be used to tailor
723communications with subprocesses to programs that exhibit unusual
724behavior with respect to buffering pipe I/O.
725
716@ifnottex 726@ifnottex
717@findex w32-shell-execute 727@findex w32-shell-execute
718 The function @code{w32-shell-execute} can be useful for writing 728 The function @code{w32-shell-execute} can be useful for writing
diff --git a/etc/NEWS b/etc/NEWS
index 85ec30ac033..10fcb7e3fd4 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1762,6 +1762,12 @@ this has no effect.
1762** The new function 'w32-application-type' returns the type of an 1762** The new function 'w32-application-type' returns the type of an
1763MS-Windows application given the name of its executable program file. 1763MS-Windows application given the name of its executable program file.
1764 1764
1765** New variable `w32-pipe-buffer-size'.
1766It can be used to tune the size of the buffer of pipes created for
1767communicating with subprocesses, when the program run by a subprocess
1768exhibits unusual buffering behavior. Default is zero, which lets the
1769OS use its default size.
1770
1765 1771
1766---------------------------------------------------------------------- 1772----------------------------------------------------------------------
1767This file is part of GNU Emacs. 1773This file is part of GNU Emacs.
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.