diff options
| author | Glenn Morris | 2013-02-15 09:31:12 -0800 |
|---|---|---|
| committer | Glenn Morris | 2013-02-15 09:31:12 -0800 |
| commit | d64d97e537301a9787a569982d67eed8ecdabe8b (patch) | |
| tree | 9eb69f45f65e4b8b3ac605e8df0aa5f8729b00a3 /src/w32proc.c | |
| parent | 0063fdb148db6352a06448053227c0924110cdda (diff) | |
| parent | a7727d05be4047b4ab6c8218ad2de5e2ad8624da (diff) | |
| download | emacs-d64d97e537301a9787a569982d67eed8ecdabe8b.tar.gz emacs-d64d97e537301a9787a569982d67eed8ecdabe8b.zip | |
Merge from emacs-24; up to 2012-12-19T19:51:40Z!monnier@iro.umontreal.ca
Diffstat (limited to 'src/w32proc.c')
| -rw-r--r-- | src/w32proc.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/w32proc.c b/src/w32proc.c index ce1474c7323..8226564c88f 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -804,6 +804,9 @@ new_child (void) | |||
| 804 | goto Initialize; | 804 | goto Initialize; |
| 805 | if (child_proc_count == MAX_CHILDREN) | 805 | if (child_proc_count == MAX_CHILDREN) |
| 806 | { | 806 | { |
| 807 | int i = 0; | ||
| 808 | child_process *dead_cp = NULL; | ||
| 809 | |||
| 807 | DebPrint (("new_child: No vacant slots, looking for dead processes\n")); | 810 | DebPrint (("new_child: No vacant slots, looking for dead processes\n")); |
| 808 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) | 811 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) |
| 809 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | 812 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) |
| @@ -819,15 +822,27 @@ new_child (void) | |||
| 819 | if (status != STILL_ACTIVE | 822 | if (status != STILL_ACTIVE |
| 820 | || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) | 823 | || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) |
| 821 | { | 824 | { |
| 822 | DebPrint (("new_child: Freeing slot of dead process %d\n", | 825 | DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n", |
| 823 | cp->procinfo.dwProcessId)); | 826 | cp->procinfo.dwProcessId, cp->fd)); |
| 824 | CloseHandle (cp->procinfo.hProcess); | 827 | CloseHandle (cp->procinfo.hProcess); |
| 825 | cp->procinfo.hProcess = NULL; | 828 | cp->procinfo.hProcess = NULL; |
| 826 | CloseHandle (cp->procinfo.hThread); | 829 | CloseHandle (cp->procinfo.hThread); |
| 827 | cp->procinfo.hThread = NULL; | 830 | cp->procinfo.hThread = NULL; |
| 828 | goto Initialize; | 831 | /* Free up to 2 dead slots at a time, so that if we |
| 832 | have a lot of them, they will eventually all be | ||
| 833 | freed when the tornado ends. */ | ||
| 834 | if (i == 0) | ||
| 835 | dead_cp = cp; | ||
| 836 | else | ||
| 837 | break; | ||
| 838 | i++; | ||
| 829 | } | 839 | } |
| 830 | } | 840 | } |
| 841 | if (dead_cp) | ||
| 842 | { | ||
| 843 | cp = dead_cp; | ||
| 844 | goto Initialize; | ||
| 845 | } | ||
| 831 | } | 846 | } |
| 832 | if (child_proc_count == MAX_CHILDREN) | 847 | if (child_proc_count == MAX_CHILDREN) |
| 833 | return NULL; | 848 | return NULL; |
| @@ -1002,12 +1017,24 @@ reader_thread (void *arg) | |||
| 1002 | if (cp->status == STATUS_READ_ERROR || !cp->char_avail) | 1017 | if (cp->status == STATUS_READ_ERROR || !cp->char_avail) |
| 1003 | break; | 1018 | break; |
| 1004 | 1019 | ||
| 1020 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess && cp->fd >= 0) | ||
| 1021 | { | ||
| 1022 | /* Somebody already called delete_child on this child, since | ||
| 1023 | only delete_child zeroes out cp->char_avail. This means | ||
| 1024 | no one will read from cp->fd and will not set the | ||
| 1025 | FILE_AT_EOF flag, therefore preventing sys_select from | ||
| 1026 | noticing that the process died. Set the flag here | ||
| 1027 | instead. */ | ||
| 1028 | fd_info[cp->fd].flags |= FILE_AT_EOF; | ||
| 1029 | } | ||
| 1030 | |||
| 1005 | /* The name char_avail is a misnomer - it really just means the | 1031 | /* The name char_avail is a misnomer - it really just means the |
| 1006 | read-ahead has completed, whether successfully or not. */ | 1032 | read-ahead has completed, whether successfully or not. */ |
| 1007 | if (!SetEvent (cp->char_avail)) | 1033 | if (!SetEvent (cp->char_avail)) |
| 1008 | { | 1034 | { |
| 1009 | DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", | 1035 | DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n", |
| 1010 | GetLastError (), cp->fd)); | 1036 | (DWORD_PTR)cp->char_avail, GetLastError (), |
| 1037 | cp->fd, cp->pid)); | ||
| 1011 | return 1; | 1038 | return 1; |
| 1012 | } | 1039 | } |
| 1013 | 1040 | ||
| @@ -1210,6 +1237,11 @@ reap_subprocess (child_process *cp) | |||
| 1210 | sys_read when the subprocess output is fully read. */ | 1237 | sys_read when the subprocess output is fully read. */ |
| 1211 | if (cp->fd < 0) | 1238 | if (cp->fd < 0) |
| 1212 | delete_child (cp); | 1239 | delete_child (cp); |
| 1240 | else | ||
| 1241 | { | ||
| 1242 | /* Reset the flag set by reader_thread. */ | ||
| 1243 | fd_info[cp->fd].flags &= ~FILE_AT_EOF; | ||
| 1244 | } | ||
| 1213 | } | 1245 | } |
| 1214 | 1246 | ||
| 1215 | /* Wait for a child process specified by PID, or for any of our | 1247 | /* Wait for a child process specified by PID, or for any of our |
| @@ -2035,7 +2067,7 @@ count_children: | |||
| 2035 | /* Some child_procs might be sockets; ignore them. Also some | 2067 | /* Some child_procs might be sockets; ignore them. Also some |
| 2036 | children may have died already, but we haven't finished reading | 2068 | children may have died already, but we haven't finished reading |
| 2037 | the process output; ignore them too. */ | 2069 | the process output; ignore them too. */ |
| 2038 | if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess | 2070 | if ((CHILD_ACTIVE (cp) || cp->procinfo.hProcess) |
| 2039 | && (cp->fd < 0 | 2071 | && (cp->fd < 0 |
| 2040 | || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 | 2072 | || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 |
| 2041 | || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) | 2073 | || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) |