]> code.delx.au - gnu-emacs/commitdiff
A possible fix for bug #14333 with hanging at exit on MS-Windows.
authorEli Zaretskii <eliz@gnu.org>
Thu, 29 Aug 2013 15:32:04 +0000 (18:32 +0300)
committerEli Zaretskii <eliz@gnu.org>
Thu, 29 Aug 2013 15:32:04 +0000 (18:32 +0300)
 src/w32.c (term_winsock): Call release_listen_threads before calling
 WSACleanup.
 (_sys_wait_accept): Wait for accept event in a loop with a finite
 timeout, instead of waiting indefinitely.  Will hopefully avoid
 hanging during exit because WSACleanup deadlocks waiting for the
 event object to be released.
 src/w32proc.c (release_listen_threads): New function, signals all
 the reader threads that listen for connections to stop waiting.
 src/w32.h (release_listen_threads): Add prototype.

src/ChangeLog
src/w32.c
src/w32.h
src/w32proc.c

index a020c1278e39b33bd2a5b9e506d9e6ec75000736..0a24427f683e46818cec6e74591bcce296fabbca 100644 (file)
@@ -1,3 +1,17 @@
+2013-08-29  Eli Zaretskii  <eliz@gnu.org>
+
+       * w32.c (term_winsock): Call release_listen_threads before calling
+       WSACleanup.
+       (_sys_wait_accept): Wait for accept event in a loop with a finite
+       timeout, instead of waiting indefinitely.  Will hopefully avoid
+       hanging during exit because WSACleanup deadlocks waiting for the
+       event object to be released.  (Bug#14333)
+
+       * w32proc.c (release_listen_threads): New function, signals all
+       the reader threads that listen for connections to stop waiting.
+
+       * w32.h (release_listen_threads): Add prototype.
+
 2013-08-29  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * alloc.c (Fmake_marker, build_marker): Zero need_adjustment
index 05a3fde97ce41cd223dbbf17f46f03df185a5892..1dcf46b5f4bc1b83819256e1986be0de8cf4ae0a 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -6092,6 +6092,7 @@ term_winsock (void)
 {
   if (winsock_lib != NULL && winsock_inuse == 0)
     {
+      release_listen_threads ();
       /* Not sure what would cause WSAENETDOWN, or even if it can happen
         after WSAStartup returns successfully, but it seems reasonable
         to allow unloading winsock anyway in that case. */
@@ -7076,7 +7077,12 @@ _sys_wait_accept (int fd)
   rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
   if (rc != SOCKET_ERROR)
     {
-      rc = WaitForSingleObject (hEv, INFINITE);
+      do {
+       rc = WaitForSingleObject (hEv, 500);
+       Sleep (5);
+      } while (rc == WAIT_TIMEOUT
+              && cp->status != STATUS_READ_ERROR
+              && cp->char_avail);
       pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
       if (rc == WAIT_OBJECT_0)
        cp->status = STATUS_READ_SUCCEEDED;
index 9c1f1efa6994755b87eb2c41c932822d99f2c984..32d0fdbe3cfabb134a6c51449a27f298beb6b6dd 100644 (file)
--- a/src/w32.h
+++ b/src/w32.h
@@ -163,6 +163,7 @@ extern void reset_standard_handles (int in, int out,
 /* Return the string resource associated with KEY of type TYPE.  */
 extern LPBYTE w32_get_resource (char * key, LPDWORD type);
 
+extern void release_listen_threads (void);
 extern void init_ntproc (int);
 extern void term_ntproc (int);
 extern void globals_of_w32 (void);
index 54316a6f80fa6efeade567a5ae2babf1415dff8d..dabaa62f71c59402647871e16f4e68865b952c9e 100644 (file)
@@ -990,6 +990,18 @@ find_child_pid (DWORD pid)
   return NULL;
 }
 
+void
+release_listen_threads (void)
+{
+  int i;
+
+  for (i = child_proc_count - 1; i >= 0; i--)
+    {
+      if (CHILD_ACTIVE (&child_procs[i])
+         && (fd_info[child_procs[i].fd].flags & FILE_LISTEN))
+       child_procs[i].status = STATUS_READ_ERROR;
+    }
+}
 
 /* Thread proc for child process and socket reader threads. Each thread
    is normally blocked until woken by select() to check for input by