aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-12-23 19:06:58 +0200
committerEli Zaretskii2012-12-23 19:06:58 +0200
commit299614f3bcac13be9a17d038f247856e384d9dbd (patch)
tree3a1121979e537c9eaf053573a8e92e9ccf95119a /src
parent9c3dcdaafa79daaaeb26fb41ec0df1ead50c330b (diff)
downloademacs-299614f3bcac13be9a17d038f247856e384d9dbd.tar.gz
emacs-299614f3bcac13be9a17d038f247856e384d9dbd.zip
Improve handling of subprocess shutdown on MS-Windows.
src/w32proc.c (reader_thread): Do not index fd_info[] with negative values. (reader_thread): Exit when cp->status becomes STATUS_READ_ERROR after WaitForSingleObject returns normally. This expedites reader thread shutdown when delete_child triggers it. (reap_subprocess): More accurate commentary for why we call delete_child only when cp->fd is negative. src/w32.c (sys_close): Do not call delete_child on a subprocess whose handle is not yet closed. Instead, set its file descriptor to a negative value, so that reap_subprocess will call delete_child on that subprocess when its SIGCHLD arrives. This avoids closing handles used for communications between sys_select and reader_thread, which doesn't give sys_select a chance to notice that the process exited and invoke the SIGCHLD handler for it.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog19
-rw-r--r--src/w32.c16
-rw-r--r--src/w32proc.c14
3 files changed, 42 insertions, 7 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2723d8f92ec..c7502104ddf 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
12012-12-23 Eli Zaretskii <eliz@gnu.org>
2
3 * w32proc.c (reader_thread): Do not index fd_info[] with negative
4 values.
5 (reader_thread): Exit when cp->status becomes STATUS_READ_ERROR
6 after WaitForSingleObject returns normally. This expedites reader
7 thread shutdown when delete_child triggers it.
8 (reap_subprocess): More accurate commentary for why we call
9 delete_child only when cp->fd is negative.
10
11 * w32.c (sys_close): Do not call delete_child on a subprocess
12 whose handle is not yet closed. Instead, set its file descriptor
13 to a negative value, so that reap_subprocess will call
14 delete_child on that subprocess when its SIGCHLD arrives. This
15 avoids closing handles used for communications between sys_select
16 and reader_thread, which doesn't give sys_select a chance to
17 notice that the process exited and invoke the SIGCHLD handler for
18 it.
19
12012-12-23 Jan Djärv <jan.h.d@swipnet.se> 202012-12-23 Jan Djärv <jan.h.d@swipnet.se>
2 21
3 * nsfns.m (Fns_do_applescript): Run event loop until script has 22 * nsfns.m (Fns_do_applescript): Run event loop until script has
diff --git a/src/w32.c b/src/w32.c
index aa3431a1357..47b950668b0 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -6401,7 +6401,21 @@ sys_close (int fd)
6401 6401
6402 winsock_inuse--; /* count open sockets */ 6402 winsock_inuse--; /* count open sockets */
6403 } 6403 }
6404 delete_child (cp); 6404 /* If the process handle is NULL, it's either a socket
6405 or serial connection, or a subprocess that was
6406 already reaped by reap_subprocess, but whose
6407 resources were not yet freed, because its output was
6408 not fully read yet by the time it was reaped. (This
6409 usually happens with async subprocesses whose output
6410 is being read by Emacs.) Otherwise, this process was
6411 not reaped yet, so we set its FD to a negative value
6412 to make sure sys_select will eventually get to
6413 calling the SIGCHLD handler for it, which will then
6414 invoke waitpid and reap_subprocess. */
6415 if (cp->procinfo.hProcess == NULL)
6416 delete_child (cp);
6417 else
6418 cp->fd = -1;
6405 } 6419 }
6406 } 6420 }
6407 } 6421 }
diff --git a/src/w32proc.c b/src/w32proc.c
index 1693b2ad501..5c43a57db29 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -965,7 +965,7 @@ reader_thread (void *arg)
965 { 965 {
966 int rc; 966 int rc;
967 967
968 if (fd_info[cp->fd].flags & FILE_LISTEN) 968 if (cp->fd >= 0 && fd_info[cp->fd].flags & FILE_LISTEN)
969 rc = _sys_wait_accept (cp->fd); 969 rc = _sys_wait_accept (cp->fd);
970 else 970 else
971 rc = _sys_read_ahead (cp->fd); 971 rc = _sys_read_ahead (cp->fd);
@@ -993,6 +993,8 @@ reader_thread (void *arg)
993 "%lu for fd %ld\n", GetLastError (), cp->fd)); 993 "%lu for fd %ld\n", GetLastError (), cp->fd));
994 break; 994 break;
995 } 995 }
996 if (cp->status == STATUS_READ_ERROR)
997 break;
996 } 998 }
997 return 0; 999 return 0;
998} 1000}
@@ -1163,11 +1165,11 @@ reap_subprocess (child_process *cp)
1163 cp->procinfo.hThread = NULL; 1165 cp->procinfo.hThread = NULL;
1164 } 1166 }
1165 1167
1166 /* For asynchronous children, the child_proc resources will be freed 1168 /* If cp->fd was not closed yet, we might be still reading the
1167 when the last pipe read descriptor is closed; for synchronous 1169 process output, so don't free its resources just yet. The call
1168 children, we must explicitly free the resources now because 1170 to delete_child on behalf of this subprocess will be made by
1169 register_child has not been called. */ 1171 sys_read when the subprocess output is fully read. */
1170 if (cp->fd == -1) 1172 if (cp->fd < 0)
1171 delete_child (cp); 1173 delete_child (cp);
1172} 1174}
1173 1175