]> code.delx.au - gnu-emacs/commitdiff
Merge from emacs-24; up to 2012-12-19T19:51:40Z!monnier@iro.umontreal.ca
authorGlenn Morris <rgm@gnu.org>
Fri, 15 Feb 2013 17:31:12 +0000 (09:31 -0800)
committerGlenn Morris <rgm@gnu.org>
Fri, 15 Feb 2013 17:31:12 +0000 (09:31 -0800)
doc/lispref/ChangeLog
src/ChangeLog
src/w32.c
src/w32proc.c

index ffda87384b5438708e60e2c54ec8342e46bcf2b7..d8a08ee5d3e03b5d795684241cabd7d2db0985b6 100644 (file)
@@ -1,4 +1,4 @@
-2013-02-14  Glenn Morris  <rgm@gnu.org>
+2013-02-15  Glenn Morris  <rgm@gnu.org>
 
        * modes.texi (Basic Major Modes): 'z' no longer bound in special-mode.
 
index 448f1e1ca0f844fa190956023b64ee58aad02a79..1e1fe641ee5ed9c6836acd6284f0c7b686f3968c 100644 (file)
@@ -1,3 +1,27 @@
+2013-02-15  Eli Zaretskii  <eliz@gnu.org>
+
+       * w32proc.c (new_child): Free up to 2 slots of dead processes at a
+       time.  Improve diagnostics in DebPrint.
+       (reader_thread): If cp->char_avail is NULL, set the FILE_AT_EOF
+       flag, so that sys_select could have a chance of noticing that this
+       process is dead, and call a SIGCHLD handler for it.  Improve
+       diagnostics in DebPrint.
+       (reap_subprocess): Reset the FILE_AT_EOF flag set by
+       reader_thread.
+       (sys_select): Watch a process whose procinfo.hProcess is non-NULL
+       even if its char_avail is NULL.  Allows to reap subprocesses that
+       were forcibly deleted by delete-process.  (Bug#13546)
+
+       * w32.c (sys_socket, sys_bind, sys_connect, sys_gethostname)
+       (sys_gethostbyname, sys_getservbyname, sys_getpeername)
+       (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname)
+       (sys_accept, sys_recvfrom, sys_sendto, fcntl): In case of failure,
+       make sure errno is set to an appropriate value.  (Bug#13546)
+       (socket_to_fd): Add assertion against indexing fd_info[] with a
+       value that is out of bounds.
+       (sys_accept): If fd is negative, do not set up the child_process
+       structure for reading.
+
 2013-02-15  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * composite.c (fill_gstring_header): Remove useless prototype.
index 03e65bf943118c619ea056d0b7fe4e816aa4c02f..25cc2185793620266ce7cc35d91344abfb444b6e 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -6232,7 +6232,7 @@ sys_socket (int af, int type, int protocol)
 
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return INVALID_SOCKET;
     }
 
@@ -6242,7 +6242,13 @@ sys_socket (int af, int type, int protocol)
   s = pfn_socket (af, type, protocol);
 
   if (s != INVALID_SOCKET)
-    return socket_to_fd (s);
+    {
+      int retval = socket_to_fd (s);
+
+      if (retval == -1)
+       errno = h_errno;
+      return retval;
+    }
 
   set_errno ();
   return -1;
@@ -6309,6 +6315,7 @@ socket_to_fd (SOCKET s)
              }
          }
       }
+      eassert (fd < MAXDESC);
       fd_info[fd].hnd = (HANDLE) s;
 
       /* set our own internal flags */
@@ -6347,7 +6354,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENOTSOCK;
+      errno = h_errno = ENOTSOCK;
       return SOCKET_ERROR;
     }
 
@@ -6359,7 +6366,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6368,7 +6375,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENOTSOCK;
+      errno = h_errno = ENOTSOCK;
       return SOCKET_ERROR;
     }
 
@@ -6380,7 +6387,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6414,7 +6421,7 @@ sys_gethostname (char * name, int namelen)
   if (namelen > MAX_COMPUTERNAME_LENGTH)
     return !GetComputerName (name, (DWORD *)&namelen);
 
-  h_errno = EFAULT;
+  errno = h_errno = EFAULT;
   return SOCKET_ERROR;
 }
 
@@ -6425,7 +6432,7 @@ sys_gethostbyname (const char * name)
 
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return NULL;
     }
 
@@ -6443,7 +6450,7 @@ sys_getservbyname (const char * name, const char * proto)
 
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return NULL;
     }
 
@@ -6459,7 +6466,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6471,7 +6478,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6480,7 +6487,7 @@ sys_shutdown (int s, int how)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6492,7 +6499,7 @@ sys_shutdown (int s, int how)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6501,7 +6508,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6514,7 +6521,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6523,7 +6530,7 @@ sys_listen (int s, int backlog)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6537,7 +6544,7 @@ sys_listen (int s, int backlog)
        fd_info[s].flags |= FILE_LISTEN;
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6546,7 +6553,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6558,7 +6565,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen)
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6567,7 +6574,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return -1;
     }
 
@@ -6579,13 +6586,20 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
       if (t == INVALID_SOCKET)
        set_errno ();
       else
-       fd = socket_to_fd (t);
+       {
+         fd = socket_to_fd (t);
+         if (fd < 0)
+           errno = h_errno;    /* socket_to_fd sets h_errno */
+       }
 
-      fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
-      ResetEvent (fd_info[s].cp->char_avail);
+      if (fd >= 0)
+       {
+         fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
+         ResetEvent (fd_info[s].cp->char_avail);
+       }
       return fd;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return -1;
 }
 
@@ -6595,7 +6609,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6607,7 +6621,7 @@ sys_recvfrom (int s, char * buf, int len, int flags,
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6617,7 +6631,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return SOCKET_ERROR;
     }
 
@@ -6629,7 +6643,7 @@ sys_sendto (int s, const char * buf, int len, int flags,
        set_errno ();
       return rc;
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
@@ -6640,7 +6654,7 @@ fcntl (int s, int cmd, int options)
 {
   if (winsock_lib == NULL)
     {
-      h_errno = ENETDOWN;
+      errno = h_errno = ENETDOWN;
       return -1;
     }
 
@@ -6663,7 +6677,7 @@ fcntl (int s, int cmd, int options)
          return SOCKET_ERROR;
        }
     }
-  h_errno = ENOTSOCK;
+  errno = h_errno = ENOTSOCK;
   return SOCKET_ERROR;
 }
 
index ce1474c732304506adb02f2039286b59a95a7afb..8226564c88fe388a844bbda9ba7bc8971be69c1f 100644 (file)
@@ -804,6 +804,9 @@ new_child (void)
       goto Initialize;
   if (child_proc_count == MAX_CHILDREN)
     {
+      int i = 0;
+      child_process *dead_cp = NULL;
+
       DebPrint (("new_child: No vacant slots, looking for dead processes\n"));
       for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
        if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess)
@@ -819,15 +822,27 @@ new_child (void)
            if (status != STILL_ACTIVE
                || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0)
              {
-               DebPrint (("new_child: Freeing slot of dead process %d\n",
-                          cp->procinfo.dwProcessId));
+               DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n",
+                          cp->procinfo.dwProcessId, cp->fd));
                CloseHandle (cp->procinfo.hProcess);
                cp->procinfo.hProcess = NULL;
                CloseHandle (cp->procinfo.hThread);
                cp->procinfo.hThread = NULL;
-               goto Initialize;
+               /* Free up to 2 dead slots at a time, so that if we
+                  have a lot of them, they will eventually all be
+                  freed when the tornado ends.  */
+               if (i == 0)
+                 dead_cp = cp;
+               else
+                 break;
+               i++;
              }
          }
+      if (dead_cp)
+       {
+         cp = dead_cp;
+         goto Initialize;
+       }
     }
   if (child_proc_count == MAX_CHILDREN)
     return NULL;
@@ -1002,12 +1017,24 @@ reader_thread (void *arg)
       if (cp->status == STATUS_READ_ERROR || !cp->char_avail)
        break;
 
+      if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess && cp->fd >= 0)
+       {
+         /* Somebody already called delete_child on this child, since
+            only delete_child zeroes out cp->char_avail.  This means
+            no one will read from cp->fd and will not set the
+            FILE_AT_EOF flag, therefore preventing sys_select from
+            noticing that the process died.  Set the flag here
+            instead.  */
+         fd_info[cp->fd].flags |= FILE_AT_EOF;
+       }
+
       /* The name char_avail is a misnomer - it really just means the
         read-ahead has completed, whether successfully or not. */
       if (!SetEvent (cp->char_avail))
         {
-         DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
-                    GetLastError (), cp->fd));
+         DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n",
+                    (DWORD_PTR)cp->char_avail, GetLastError (),
+                    cp->fd, cp->pid));
          return 1;
        }
 
@@ -1210,6 +1237,11 @@ reap_subprocess (child_process *cp)
      sys_read when the subprocess output is fully read.  */
   if (cp->fd < 0)
     delete_child (cp);
+  else
+    {
+      /* Reset the flag set by reader_thread.  */
+      fd_info[cp->fd].flags &= ~FILE_AT_EOF;
+    }
 }
 
 /* Wait for a child process specified by PID, or for any of our
@@ -2035,7 +2067,7 @@ count_children:
     /* Some child_procs might be sockets; ignore them.  Also some
        children may have died already, but we haven't finished reading
        the process output; ignore them too.  */
-    if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
+    if ((CHILD_ACTIVE (cp) || cp->procinfo.hProcess)
        && (cp->fd < 0
            || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0
            || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)