aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-09-14 18:18:39 +0300
committerEli Zaretskii2014-09-14 18:18:39 +0300
commit9ed670023f6d7534f0e812417fe13ab3cfadaa7a (patch)
tree06b0c29a6085e82fdb3ddd02c15bd236c6d10006 /src
parenta6cc335aef90cb4a2dc3fde77cbea9886240301e (diff)
downloademacs-9ed670023f6d7534f0e812417fe13ab3cfadaa7a.tar.gz
emacs-9ed670023f6d7534f0e812417fe13ab3cfadaa7a.zip
Fix bug #18420 with deadlocks communicating with subprocess on MS-Windows.
src/w32.c (fcntl): Support O_NONBLOCK fcntl on the write side of pipes. (sys_write): When a write to a non-blocking pipe returns ENOSPC, set errno to EAGAIN instead, to allow the caller to retry the write after some waiting. Fixes deadlocks when Emacs exchanges a lot of data through the pipe.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog9
-rw-r--r--src/w32.c54
2 files changed, 55 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4f851edb0fd..c32b4c44988 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
12014-09-14 Eli Zaretskii <eliz@gnu.org>
2
3 * w32.c (fcntl): Support O_NONBLOCK fcntl on the write side of
4 pipes.
5 (sys_write): When a write to a non-blocking pipe returns ENOSPC,
6 set errno to EAGAIN instead, to allow the caller to retry the
7 write after some waiting. Fixes deadlocks when Emacs exchanges a
8 lot of data through the pipe. (Bug#18420)
9
12014-09-13 Eli Zaretskii <eliz@gnu.org> 102014-09-13 Eli Zaretskii <eliz@gnu.org>
2 11
3 * sound.c (Fplay_sound_internal): Encode the sound file name in 12 * sound.c (Fplay_sound_internal): Encode the sound file name in
diff --git a/src/w32.c b/src/w32.c
index fee1be22739..aba0b5a81f9 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -7690,15 +7690,15 @@ fcntl (int s, int cmd, int options)
7690 if (cmd == F_DUPFD_CLOEXEC) 7690 if (cmd == F_DUPFD_CLOEXEC)
7691 return sys_dup (s); 7691 return sys_dup (s);
7692 7692
7693 if (winsock_lib == NULL)
7694 {
7695 errno = ENETDOWN;
7696 return -1;
7697 }
7698
7699 check_errno (); 7693 check_errno ();
7700 if (fd_info[s].flags & FILE_SOCKET) 7694 if (fd_info[s].flags & FILE_SOCKET)
7701 { 7695 {
7696 if (winsock_lib == NULL)
7697 {
7698 errno = ENETDOWN;
7699 return -1;
7700 }
7701
7702 if (cmd == F_SETFL && options == O_NONBLOCK) 7702 if (cmd == F_SETFL && options == O_NONBLOCK)
7703 { 7703 {
7704 unsigned long nblock = 1; 7704 unsigned long nblock = 1;
@@ -7715,13 +7715,36 @@ fcntl (int s, int cmd, int options)
7715 return SOCKET_ERROR; 7715 return SOCKET_ERROR;
7716 } 7716 }
7717 } 7717 }
7718 else if ((fd_info[s].flags & (FILE_PIPE | FILE_WRITE))
7719 == (FILE_PIPE | FILE_WRITE))
7720 {
7721 /* Force our writes to pipes be non-blocking. */
7722 if (cmd == F_SETFL && options == O_NONBLOCK)
7723 {
7724 HANDLE h = (HANDLE)_get_osfhandle (s);
7725 DWORD pipe_mode = PIPE_NOWAIT;
7726
7727 if (!SetNamedPipeHandleState (h, &pipe_mode, NULL, NULL))
7728 {
7729 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
7730 return SOCKET_ERROR;
7731 }
7732 fd_info[s].flags |= FILE_NDELAY;
7733 return 0;
7734 }
7735 else
7736 {
7737 errno = EINVAL;
7738 return SOCKET_ERROR;
7739 }
7740 }
7718 errno = ENOTSOCK; 7741 errno = ENOTSOCK;
7719 return SOCKET_ERROR; 7742 return SOCKET_ERROR;
7720} 7743}
7721 7744
7722 7745
7723/* Shadow main io functions: we need to handle pipes and sockets more 7746/* Shadow main io functions: we need to handle pipes and sockets more
7724 intelligently, and implement non-blocking mode as well. */ 7747 intelligently. */
7725 7748
7726int 7749int
7727sys_close (int fd) 7750sys_close (int fd)
@@ -8206,7 +8229,6 @@ sys_read (int fd, char * buffer, unsigned int count)
8206/* From w32xfns.c */ 8229/* From w32xfns.c */
8207extern HANDLE interrupt_handle; 8230extern HANDLE interrupt_handle;
8208 8231
8209/* For now, don't bother with a non-blocking mode */
8210int 8232int
8211sys_write (int fd, const void * buffer, unsigned int count) 8233sys_write (int fd, const void * buffer, unsigned int count)
8212{ 8234{
@@ -8341,6 +8363,22 @@ sys_write (int fd, const void * buffer, unsigned int count)
8341 nchars += n; 8363 nchars += n;
8342 if (n < 0) 8364 if (n < 0)
8343 { 8365 {
8366 /* When there's no buffer space in a pipe that is in the
8367 non-blocking mode, _write returns ENOSPC. We return
8368 EAGAIN instead, which should trigger the logic in
8369 send_process that enters waiting loop and calls
8370 wait_reading_process_output to allow process input to
8371 be accepted during the wait. Those calls to
8372 wait_reading_process_output allow sys_select to
8373 notice when process input becomes available, thus
8374 avoiding deadlock whereby each side of the pipe is
8375 blocked on write, waiting for the other party to read
8376 its end of the pipe. */
8377 if (errno == ENOSPC
8378 && fd < MAXDESC
8379 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
8380 == (FILE_PIPE | FILE_NDELAY)))
8381 errno = EAGAIN;
8344 nchars = n; 8382 nchars = n;
8345 break; 8383 break;
8346 } 8384 }