diff options
| author | Eli Zaretskii | 2013-08-29 18:32:04 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-08-29 18:32:04 +0300 |
| commit | 3f940c5aa6fc1d03e6658cda5c440fb6bd75e4c5 (patch) | |
| tree | 5729694efb5e29a00b9fad2f9c081d2198f3ccc9 /src | |
| parent | 20de2834a594370b2f30fa55932c9de3da6150ed (diff) | |
| download | emacs-3f940c5aa6fc1d03e6658cda5c440fb6bd75e4c5.tar.gz emacs-3f940c5aa6fc1d03e6658cda5c440fb6bd75e4c5.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 14 | ||||
| -rw-r--r-- | src/w32.c | 8 | ||||
| -rw-r--r-- | src/w32.h | 1 | ||||
| -rw-r--r-- | src/w32proc.c | 12 |
4 files changed, 34 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a020c1278e3..0a24427f683 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,17 @@ | |||
| 1 | 2013-08-29 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * w32.c (term_winsock): Call release_listen_threads before calling | ||
| 4 | WSACleanup. | ||
| 5 | (_sys_wait_accept): Wait for accept event in a loop with a finite | ||
| 6 | timeout, instead of waiting indefinitely. Will hopefully avoid | ||
| 7 | hanging during exit because WSACleanup deadlocks waiting for the | ||
| 8 | event object to be released. (Bug#14333) | ||
| 9 | |||
| 10 | * w32proc.c (release_listen_threads): New function, signals all | ||
| 11 | the reader threads that listen for connections to stop waiting. | ||
| 12 | |||
| 13 | * w32.h (release_listen_threads): Add prototype. | ||
| 14 | |||
| 1 | 2013-08-29 Dmitry Antipov <dmantipov@yandex.ru> | 15 | 2013-08-29 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 16 | ||
| 3 | * alloc.c (Fmake_marker, build_marker): Zero need_adjustment | 17 | * alloc.c (Fmake_marker, build_marker): Zero need_adjustment |
| @@ -6092,6 +6092,7 @@ term_winsock (void) | |||
| 6092 | { | 6092 | { |
| 6093 | if (winsock_lib != NULL && winsock_inuse == 0) | 6093 | if (winsock_lib != NULL && winsock_inuse == 0) |
| 6094 | { | 6094 | { |
| 6095 | release_listen_threads (); | ||
| 6095 | /* Not sure what would cause WSAENETDOWN, or even if it can happen | 6096 | /* Not sure what would cause WSAENETDOWN, or even if it can happen |
| 6096 | after WSAStartup returns successfully, but it seems reasonable | 6097 | after WSAStartup returns successfully, but it seems reasonable |
| 6097 | to allow unloading winsock anyway in that case. */ | 6098 | to allow unloading winsock anyway in that case. */ |
| @@ -7076,7 +7077,12 @@ _sys_wait_accept (int fd) | |||
| 7076 | rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT); | 7077 | rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT); |
| 7077 | if (rc != SOCKET_ERROR) | 7078 | if (rc != SOCKET_ERROR) |
| 7078 | { | 7079 | { |
| 7079 | rc = WaitForSingleObject (hEv, INFINITE); | 7080 | do { |
| 7081 | rc = WaitForSingleObject (hEv, 500); | ||
| 7082 | Sleep (5); | ||
| 7083 | } while (rc == WAIT_TIMEOUT | ||
| 7084 | && cp->status != STATUS_READ_ERROR | ||
| 7085 | && cp->char_avail); | ||
| 7080 | pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0); | 7086 | pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0); |
| 7081 | if (rc == WAIT_OBJECT_0) | 7087 | if (rc == WAIT_OBJECT_0) |
| 7082 | cp->status = STATUS_READ_SUCCEEDED; | 7088 | cp->status = STATUS_READ_SUCCEEDED; |
| @@ -163,6 +163,7 @@ extern void reset_standard_handles (int in, int out, | |||
| 163 | /* Return the string resource associated with KEY of type TYPE. */ | 163 | /* Return the string resource associated with KEY of type TYPE. */ |
| 164 | extern LPBYTE w32_get_resource (char * key, LPDWORD type); | 164 | extern LPBYTE w32_get_resource (char * key, LPDWORD type); |
| 165 | 165 | ||
| 166 | extern void release_listen_threads (void); | ||
| 166 | extern void init_ntproc (int); | 167 | extern void init_ntproc (int); |
| 167 | extern void term_ntproc (int); | 168 | extern void term_ntproc (int); |
| 168 | extern void globals_of_w32 (void); | 169 | 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) | |||
| 990 | return NULL; | 990 | return NULL; |
| 991 | } | 991 | } |
| 992 | 992 | ||
| 993 | void | ||
| 994 | release_listen_threads (void) | ||
| 995 | { | ||
| 996 | int i; | ||
| 997 | |||
| 998 | for (i = child_proc_count - 1; i >= 0; i--) | ||
| 999 | { | ||
| 1000 | if (CHILD_ACTIVE (&child_procs[i]) | ||
| 1001 | && (fd_info[child_procs[i].fd].flags & FILE_LISTEN)) | ||
| 1002 | child_procs[i].status = STATUS_READ_ERROR; | ||
| 1003 | } | ||
| 1004 | } | ||
| 993 | 1005 | ||
| 994 | /* Thread proc for child process and socket reader threads. Each thread | 1006 | /* Thread proc for child process and socket reader threads. Each thread |
| 995 | is normally blocked until woken by select() to check for input by | 1007 | is normally blocked until woken by select() to check for input by |