diff options
| author | Eli Zaretskii | 2013-02-17 20:17:34 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-02-17 20:17:34 +0200 |
| commit | ae11bda519726c8619f687645138f913b1027be3 (patch) | |
| tree | 50f479da0a7572017d55baf6eb017ef6012c58f4 /src | |
| parent | fd80c659d21fa9f42ae0f862fb51580afa63fdd0 (diff) | |
| download | emacs-ae11bda519726c8619f687645138f913b1027be3.tar.gz emacs-ae11bda519726c8619f687645138f913b1027be3.zip | |
Fix bug #13735 with network streams on MS-Windows.
Revert changes to w32proc.c done since 2012-11-30T09:23:15Z!eliz@gnu.org.
Do NOT merge to trunk!
src/w32proc.c (new_child): Remove the loop that attempted to salvage
slots of dead processes.
(new_child, delete_child, find_child_pid): Don't insist on
procinfo.hProcess be NULL for a process slot to be considered
inactive, or be non-NULL to be considered active.
(reader_thread): Don't set the FILE_AT_EOF flag of a file
descriptor if the corresponding child was deleted and its
char_avail handle is NULL.
(reap_subprocess): Don't reset the FILE_AT_EOF flag.
(sys_select): Don't pass a NULL process handle to
WaitForMultipleObjects.
Fixes: debbugs:13735 debbugs:13546
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 12 | ||||
| -rw-r--r-- | src/w32proc.c | 70 |
2 files changed, 17 insertions, 65 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 06207f6690e..4325d35adee 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,17 @@ | |||
| 1 | 2013-02-17 Eli Zaretskii <eliz@gnu.org> | 1 | 2013-02-17 Eli Zaretskii <eliz@gnu.org> |
| 2 | 2 | ||
| 3 | * w32proc.c (new_child): Remove the loop that attempted to salvage | ||
| 4 | slots of dead processes. | ||
| 5 | (new_child, delete_child, find_child_pid): Don't insist on | ||
| 6 | procinfo.hProcess be NULL for a process slot to be considered | ||
| 7 | inactive, or be non-NULL to be considered active. | ||
| 8 | (reader_thread): Don't set the FILE_AT_EOF flag of a file | ||
| 9 | descriptor if the corresponding child was deleted and its | ||
| 10 | char_avail handle is NULL. | ||
| 11 | (reap_subprocess): Don't reset the FILE_AT_EOF flag. (Bug#13546) | ||
| 12 | (sys_select): Don't pass a NULL process handle to | ||
| 13 | WaitForMultipleObjects. (Bug#13735) | ||
| 14 | |||
| 3 | * xdisp.c (x_draw_vertical_border): For a window that is neither | 15 | * xdisp.c (x_draw_vertical_border): For a window that is neither |
| 4 | the leftmost nor the rightmost, redraw both the left and the right | 16 | the leftmost nor the rightmost, redraw both the left and the right |
| 5 | vertical borders. (Bug#13723) | 17 | vertical borders. (Bug#13723) |
diff --git a/src/w32proc.c b/src/w32proc.c index ca2096aaa9d..3b4522bf16b 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -795,51 +795,9 @@ new_child (void) | |||
| 795 | DWORD id; | 795 | DWORD id; |
| 796 | 796 | ||
| 797 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) | 797 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) |
| 798 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL) | 798 | if (!CHILD_ACTIVE (cp)) |
| 799 | goto Initialize; | 799 | goto Initialize; |
| 800 | if (child_proc_count == MAX_CHILDREN) | 800 | if (child_proc_count == MAX_CHILDREN) |
| 801 | { | ||
| 802 | int i = 0; | ||
| 803 | child_process *dead_cp = NULL; | ||
| 804 | |||
| 805 | DebPrint (("new_child: No vacant slots, looking for dead processes\n")); | ||
| 806 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) | ||
| 807 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) | ||
| 808 | { | ||
| 809 | DWORD status = 0; | ||
| 810 | |||
| 811 | if (!GetExitCodeProcess (cp->procinfo.hProcess, &status)) | ||
| 812 | { | ||
| 813 | DebPrint (("new_child.GetExitCodeProcess: error %lu for PID %lu\n", | ||
| 814 | GetLastError (), cp->procinfo.dwProcessId)); | ||
| 815 | status = STILL_ACTIVE; | ||
| 816 | } | ||
| 817 | if (status != STILL_ACTIVE | ||
| 818 | || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) | ||
| 819 | { | ||
| 820 | DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n", | ||
| 821 | cp->procinfo.dwProcessId, cp->fd)); | ||
| 822 | CloseHandle (cp->procinfo.hProcess); | ||
| 823 | cp->procinfo.hProcess = NULL; | ||
| 824 | CloseHandle (cp->procinfo.hThread); | ||
| 825 | cp->procinfo.hThread = NULL; | ||
| 826 | /* Free up to 2 dead slots at a time, so that if we | ||
| 827 | have a lot of them, they will eventually all be | ||
| 828 | freed when the tornado ends. */ | ||
| 829 | if (i == 0) | ||
| 830 | dead_cp = cp; | ||
| 831 | else | ||
| 832 | break; | ||
| 833 | i++; | ||
| 834 | } | ||
| 835 | } | ||
| 836 | if (dead_cp) | ||
| 837 | { | ||
| 838 | cp = dead_cp; | ||
| 839 | goto Initialize; | ||
| 840 | } | ||
| 841 | } | ||
| 842 | if (child_proc_count == MAX_CHILDREN) | ||
| 843 | return NULL; | 801 | return NULL; |
| 844 | cp = &child_procs[child_proc_count++]; | 802 | cp = &child_procs[child_proc_count++]; |
| 845 | 803 | ||
| @@ -894,7 +852,7 @@ delete_child (child_process *cp) | |||
| 894 | if (fd_info[i].cp == cp) | 852 | if (fd_info[i].cp == cp) |
| 895 | emacs_abort (); | 853 | emacs_abort (); |
| 896 | 854 | ||
| 897 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL) | 855 | if (!CHILD_ACTIVE (cp)) |
| 898 | return; | 856 | return; |
| 899 | 857 | ||
| 900 | /* reap thread if necessary */ | 858 | /* reap thread if necessary */ |
| @@ -938,8 +896,7 @@ delete_child (child_process *cp) | |||
| 938 | if (cp == child_procs + child_proc_count - 1) | 896 | if (cp == child_procs + child_proc_count - 1) |
| 939 | { | 897 | { |
| 940 | for (i = child_proc_count-1; i >= 0; i--) | 898 | for (i = child_proc_count-1; i >= 0; i--) |
| 941 | if (CHILD_ACTIVE (&child_procs[i]) | 899 | if (CHILD_ACTIVE (&child_procs[i])) |
| 942 | || child_procs[i].procinfo.hProcess != NULL) | ||
| 943 | { | 900 | { |
| 944 | child_proc_count = i + 1; | 901 | child_proc_count = i + 1; |
| 945 | break; | 902 | break; |
| @@ -956,8 +913,7 @@ find_child_pid (DWORD pid) | |||
| 956 | child_process *cp; | 913 | child_process *cp; |
| 957 | 914 | ||
| 958 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) | 915 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) |
| 959 | if ((CHILD_ACTIVE (cp) || cp->procinfo.hProcess != NULL) | 916 | if (CHILD_ACTIVE (cp) && pid == cp->pid) |
| 960 | && pid == cp->pid) | ||
| 961 | return cp; | 917 | return cp; |
| 962 | return NULL; | 918 | return NULL; |
| 963 | } | 919 | } |
| @@ -990,17 +946,6 @@ reader_thread (void *arg) | |||
| 990 | else | 946 | else |
| 991 | rc = _sys_read_ahead (cp->fd); | 947 | rc = _sys_read_ahead (cp->fd); |
| 992 | 948 | ||
| 993 | if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess && cp->fd >= 0) | ||
| 994 | { | ||
| 995 | /* Somebody already called delete_child on this child, since | ||
| 996 | only delete_child zeroes out cp->char_avail. This means | ||
| 997 | no one will read from cp->fd and will not set the | ||
| 998 | FILE_AT_EOF flag, therefore preventing sys_select from | ||
| 999 | noticing that the process died. Set the flag here | ||
| 1000 | instead. */ | ||
| 1001 | fd_info[cp->fd].flags |= FILE_AT_EOF; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* The name char_avail is a misnomer - it really just means the | 949 | /* The name char_avail is a misnomer - it really just means the |
| 1005 | read-ahead has completed, whether successfully or not. */ | 950 | read-ahead has completed, whether successfully or not. */ |
| 1006 | if (!SetEvent (cp->char_avail)) | 951 | if (!SetEvent (cp->char_avail)) |
| @@ -1168,11 +1113,6 @@ reap_subprocess (child_process *cp) | |||
| 1168 | register_child has not been called. */ | 1113 | register_child has not been called. */ |
| 1169 | if (cp->fd == -1) | 1114 | if (cp->fd == -1) |
| 1170 | delete_child (cp); | 1115 | delete_child (cp); |
| 1171 | else | ||
| 1172 | { | ||
| 1173 | /* Reset the flag set by reader_thread. */ | ||
| 1174 | fd_info[cp->fd].flags &= ~FILE_AT_EOF; | ||
| 1175 | } | ||
| 1176 | } | 1116 | } |
| 1177 | 1117 | ||
| 1178 | /* Wait for any of our existing child processes to die | 1118 | /* Wait for any of our existing child processes to die |
| @@ -1957,7 +1897,7 @@ count_children: | |||
| 1957 | /* Some child_procs might be sockets; ignore them. Also some | 1897 | /* Some child_procs might be sockets; ignore them. Also some |
| 1958 | children may have died already, but we haven't finished reading | 1898 | children may have died already, but we haven't finished reading |
| 1959 | the process output; ignore them too. */ | 1899 | the process output; ignore them too. */ |
| 1960 | if ((CHILD_ACTIVE (cp) || cp->procinfo.hProcess) | 1900 | if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess |
| 1961 | && (cp->fd < 0 | 1901 | && (cp->fd < 0 |
| 1962 | || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 | 1902 | || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 |
| 1963 | || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) | 1903 | || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) |