[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] emacs-25 58a622d: Make piping to subprocesses more robust
From: |
Eli Zaretskii |
Subject: |
[Emacs-diffs] emacs-25 58a622d: Make piping to subprocesses more robust on MS-Windows |
Date: |
Tue, 12 Jan 2016 16:42:51 +0000 |
branch: emacs-25
commit 58a622d473112f8ff5b4bdb3e49bc6573dfd3404
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>
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'.
---
doc/emacs/msdos.texi | 14 ++++++++++++--
etc/NEWS | 6 ++++++
src/w32.c | 39 +++++++++++++++++++++++++++++++--------
src/w32proc.c | 7 +++++++
4 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index ea8a24d..6ad12d6 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
is address@hidden, the roles of these two buttons are reversed.
@node Windows Processes
address@hidden Subprocesses on Windows 9X/ME and Windows NT/2K/XP
address@hidden Subprocesses on Windows 9X/ME and Windows NT/2K/XP/Vista/7/8/10
@cindex subprocesses on MS-Windows
@cindex DOS applications, running from Emacs
@@ -663,7 +663,8 @@ is address@hidden, the roles of these two buttons are
reversed.
version) includes full support for asynchronous subprocesses.
In the Windows version, synchronous and asynchronous subprocesses work
fine on both
-Windows 9X/ME and Windows NT/2K/XP as long as you run only 32-bit Windows
+Windows 9X/ME and Windows NT/2K/XP/Vista/7/8/10 as long as you run
+only 32-bit or 64-bit Windows
applications. However, when you run a DOS application in a subprocess,
you may encounter problems or be unable to run the application at all;
and 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
any quote characters that appear; otherwise it chooses a suitable escape
character based on the type of the program.
address@hidden w32-pipe-buffer-size
+ The variable @code{w32-pipe-buffer-size} controls the size of the
+buffer Emacs requests from the system when it creates pipes for
+communications with subprocesses. The default value is zero, which
+lets the OS choose the size. Any valid positive value will request a
+buffer of that size in bytes. This can be used to tailor
+communications with subprocesses to programs that exhibit unusual
+behavior with respect to buffering pipe I/O.
+
@ifnottex
@findex w32-shell-execute
The function @code{w32-shell-execute} can be useful for writing
diff --git a/etc/NEWS b/etc/NEWS
index 85ec30a..10fcb7e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1762,6 +1762,12 @@ this has no effect.
** The new function 'w32-application-type' returns the type of an
MS-Windows application given the name of its executable program file.
+** New variable `w32-pipe-buffer-size'.
+It can be used to tune the size of the buffer of pipes created for
+communicating with subprocesses, when the program run by a subprocess
+exhibits unusual buffering behavior. Default is zero, which lets the
+OS use its default size.
+
----------------------------------------------------------------------
This file is part of GNU Emacs.
diff --git a/src/w32.c b/src/w32.c
index 4770718..ea3a9da 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -8043,14 +8043,19 @@ pipe2 (int * phandles, int pipe2_flags)
{
int rc;
unsigned flags;
+ unsigned pipe_size = 0;
eassert (pipe2_flags == (O_BINARY | O_CLOEXEC));
+ /* Allow Lisp to override the default buffer size of the pipe. */
+ if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX)
+ pipe_size = w32_pipe_buffer_size;
+
/* make pipe handles non-inheritable; when we spawn a child, we
replace the relevant handle with an inheritable one. Also put
pipes into binary mode; we will do text mode translation ourselves
if required. */
- rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
+ rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY);
if (rc == 0)
{
@@ -8632,15 +8637,35 @@ sys_write (int fd, const void * buffer, unsigned int
count)
http://thread.gmane.org/gmane.comp.version-control.git/145294
in the git mailing list. */
const unsigned char *p = buffer;
- const unsigned chunk = 30 * 1024 * 1024;
+ const bool is_pipe = (fd < MAXDESC
+ && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
+ == (FILE_PIPE | FILE_NDELAY)));
+ /* Some programs, notably Node.js's node.exe, seem to never
+ completely empty the pipe, so writing more than the size of
+ the pipe's buffer always returns ENOSPC, and we loop forever
+ between send_process and here. As a workaround, write no
+ more than the pipe's buffer can hold. */
+ DWORD pipe_buffer_size;
+ if (is_pipe)
+ {
+ if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd),
+ NULL, &pipe_buffer_size, NULL, NULL))
+ {
+ DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
+ pipe_buffer_size = 4096;
+ }
+ }
+ const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024;
nchars = 0;
+ errno = 0;
while (count > 0)
{
unsigned this_chunk = count < chunk ? count : chunk;
int n = _write (fd, p, this_chunk);
- nchars += n;
+ if (n > 0)
+ nchars += n;
if (n < 0)
{
/* 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)
avoiding deadlock whereby each side of the pipe is
blocked on write, waiting for the other party to read
its end of the pipe. */
- if (errno == ENOSPC
- && fd < MAXDESC
- && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
- == (FILE_PIPE | FILE_NDELAY)))
+ if (errno == ENOSPC && is_pipe)
errno = EAGAIN;
- nchars = n;
+ if (nchars == 0)
+ nchars = -1;
break;
}
else if (n < this_chunk)
diff --git a/src/w32proc.c b/src/w32proc.c
index a65f085..a89a985 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
process temporarily). A value of zero disables waiting entirely. */);
w32_pipe_read_delay = 50;
+ DEFVAR_INT ("w32-pipe-buffer-size", w32_pipe_buffer_size,
+ doc: /* Size of buffer for pipes created to communicate with
subprocesses.
+The size is in bytes, and must be non-negative. The default is zero,
+which lets the OS use its default size, usually 4KB (4096 bytes).
+Any negative value means to use the default value of zero. */);
+ w32_pipe_buffer_size = 0;
+
DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names,
doc: /* Non-nil means convert all-upper case file names to lower
case.
This applies when performing completions and file name expansion.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] emacs-25 58a622d: Make piping to subprocesses more robust on MS-Windows,
Eli Zaretskii <=