From 3f940c5aa6fc1d03e6658cda5c440fb6bd75e4c5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 29 Aug 2013 18:32:04 +0300 Subject: [PATCH] A possible fix for bug #14333 with hanging at exit on MS-Windows. 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 | 14 ++++++++++++++ src/w32.c | 8 +++++++- src/w32.h | 1 + src/w32proc.c | 12 ++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ChangeLog b/src/ChangeLog index a020c1278e3..0a24427f683 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2013-08-29 Eli Zaretskii + + * 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 * alloc.c (Fmake_marker, build_marker): Zero need_adjustment diff --git a/src/w32.c b/src/w32.c index 05a3fde97ce..1dcf46b5f4b 100644 --- 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; diff --git a/src/w32.h b/src/w32.h index 9c1f1efa699..32d0fdbe3cf 100644 --- 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); diff --git a/src/w32proc.c b/src/w32proc.c index 54316a6f80f..dabaa62f71c 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -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 -- 2.39.2