diff options
| author | Eli Zaretskii | 2012-12-23 19:06:58 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2012-12-23 19:06:58 +0200 |
| commit | 299614f3bcac13be9a17d038f247856e384d9dbd (patch) | |
| tree | 3a1121979e537c9eaf053573a8e92e9ccf95119a /src | |
| parent | 9c3dcdaafa79daaaeb26fb41ec0df1ead50c330b (diff) | |
| download | emacs-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/ChangeLog | 19 | ||||
| -rw-r--r-- | src/w32.c | 16 | ||||
| -rw-r--r-- | src/w32proc.c | 14 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-12-23 Jan Djärv <jan.h.d@swipnet.se> | 20 | 2012-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 |
| @@ -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 | ||