diff options
author | Glenn Morris <rgm@gnu.org> | 2013-02-15 09:31:12 -0800 |
---|---|---|
committer | Glenn Morris <rgm@gnu.org> | 2013-02-15 09:31:12 -0800 |
commit | d64d97e537301a9787a569982d67eed8ecdabe8b (patch) | |
tree | 9eb69f45f65e4b8b3ac605e8df0aa5f8729b00a3 /src | |
parent | 0063fdb148db6352a06448053227c0924110cdda (diff) | |
parent | a7727d05be4047b4ab6c8218ad2de5e2ad8624da (diff) | |
download | emacs-d64d97e537301a9787a569982d67eed8ecdabe8b.tar.gz |
Merge from emacs-24; up to 2012-12-19T19:51:40Z!monnier@iro.umontreal.ca
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 24 | ||||
-rw-r--r-- | src/w32.c | 74 | ||||
-rw-r--r-- | src/w32proc.c | 44 |
3 files changed, 106 insertions, 36 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 448f1e1ca0f..1e1fe641ee5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,27 @@ +2013-02-15 Eli Zaretskii <eliz@gnu.org> + + * w32proc.c (new_child): Free up to 2 slots of dead processes at a + time. Improve diagnostics in DebPrint. + (reader_thread): If cp->char_avail is NULL, set the FILE_AT_EOF + flag, so that sys_select could have a chance of noticing that this + process is dead, and call a SIGCHLD handler for it. Improve + diagnostics in DebPrint. + (reap_subprocess): Reset the FILE_AT_EOF flag set by + reader_thread. + (sys_select): Watch a process whose procinfo.hProcess is non-NULL + even if its char_avail is NULL. Allows to reap subprocesses that + were forcibly deleted by delete-process. (Bug#13546) + + * w32.c (sys_socket, sys_bind, sys_connect, sys_gethostname) + (sys_gethostbyname, sys_getservbyname, sys_getpeername) + (sys_shutdown, sys_setsockopt, sys_listen, sys_getsockname) + (sys_accept, sys_recvfrom, sys_sendto, fcntl): In case of failure, + make sure errno is set to an appropriate value. (Bug#13546) + (socket_to_fd): Add assertion against indexing fd_info[] with a + value that is out of bounds. + (sys_accept): If fd is negative, do not set up the child_process + structure for reading. + 2013-02-15 Dmitry Antipov <dmantipov@yandex.ru> * composite.c (fill_gstring_header): Remove useless prototype. diff --git a/src/w32.c b/src/w32.c index 03e65bf9431..25cc2185793 100644 --- a/src/w32.c +++ b/src/w32.c @@ -6232,7 +6232,7 @@ sys_socket (int af, int type, int protocol) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return INVALID_SOCKET; } @@ -6242,7 +6242,13 @@ sys_socket (int af, int type, int protocol) s = pfn_socket (af, type, protocol); if (s != INVALID_SOCKET) - return socket_to_fd (s); + { + int retval = socket_to_fd (s); + + if (retval == -1) + errno = h_errno; + return retval; + } set_errno (); return -1; @@ -6309,6 +6315,7 @@ socket_to_fd (SOCKET s) } } } + eassert (fd < MAXDESC); fd_info[fd].hnd = (HANDLE) s; /* set our own internal flags */ @@ -6347,7 +6354,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6359,7 +6366,7 @@ sys_bind (int s, const struct sockaddr * addr, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6368,7 +6375,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) { if (winsock_lib == NULL) { - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6380,7 +6387,7 @@ sys_connect (int s, const struct sockaddr * name, int namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6414,7 +6421,7 @@ sys_gethostname (char * name, int namelen) if (namelen > MAX_COMPUTERNAME_LENGTH) return !GetComputerName (name, (DWORD *)&namelen); - h_errno = EFAULT; + errno = h_errno = EFAULT; return SOCKET_ERROR; } @@ -6425,7 +6432,7 @@ sys_gethostbyname (const char * name) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return NULL; } @@ -6443,7 +6450,7 @@ sys_getservbyname (const char * name, const char * proto) if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return NULL; } @@ -6459,7 +6466,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6471,7 +6478,7 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6480,7 +6487,7 @@ sys_shutdown (int s, int how) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6492,7 +6499,7 @@ sys_shutdown (int s, int how) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6501,7 +6508,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6514,7 +6521,7 @@ sys_setsockopt (int s, int level, int optname, const void * optval, int optlen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6523,7 +6530,7 @@ sys_listen (int s, int backlog) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6537,7 +6544,7 @@ sys_listen (int s, int backlog) fd_info[s].flags |= FILE_LISTEN; return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6546,7 +6553,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6558,7 +6565,7 @@ sys_getsockname (int s, struct sockaddr * name, int * namelen) set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6567,7 +6574,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return -1; } @@ -6579,13 +6586,20 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen) if (t == INVALID_SOCKET) set_errno (); else - fd = socket_to_fd (t); + { + fd = socket_to_fd (t); + if (fd < 0) + errno = h_errno; /* socket_to_fd sets h_errno */ + } - fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; - ResetEvent (fd_info[s].cp->char_avail); + if (fd >= 0) + { + fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED; + ResetEvent (fd_info[s].cp->char_avail); + } return fd; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return -1; } @@ -6595,7 +6609,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6607,7 +6621,7 @@ sys_recvfrom (int s, char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6617,7 +6631,7 @@ sys_sendto (int s, const char * buf, int len, int flags, { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return SOCKET_ERROR; } @@ -6629,7 +6643,7 @@ sys_sendto (int s, const char * buf, int len, int flags, set_errno (); return rc; } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } @@ -6640,7 +6654,7 @@ fcntl (int s, int cmd, int options) { if (winsock_lib == NULL) { - h_errno = ENETDOWN; + errno = h_errno = ENETDOWN; return -1; } @@ -6663,7 +6677,7 @@ fcntl (int s, int cmd, int options) return SOCKET_ERROR; } } - h_errno = ENOTSOCK; + errno = h_errno = ENOTSOCK; return SOCKET_ERROR; } 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) goto Initialize; if (child_proc_count == MAX_CHILDREN) { + int i = 0; + child_process *dead_cp = NULL; + DebPrint (("new_child: No vacant slots, looking for dead processes\n")); for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess) @@ -819,15 +822,27 @@ new_child (void) if (status != STILL_ACTIVE || WaitForSingleObject (cp->procinfo.hProcess, 0) == WAIT_OBJECT_0) { - DebPrint (("new_child: Freeing slot of dead process %d\n", - cp->procinfo.dwProcessId)); + DebPrint (("new_child: Freeing slot of dead process %d, fd %d\n", + cp->procinfo.dwProcessId, cp->fd)); CloseHandle (cp->procinfo.hProcess); cp->procinfo.hProcess = NULL; CloseHandle (cp->procinfo.hThread); cp->procinfo.hThread = NULL; - goto Initialize; + /* Free up to 2 dead slots at a time, so that if we + have a lot of them, they will eventually all be + freed when the tornado ends. */ + if (i == 0) + dead_cp = cp; + else + break; + i++; } } + if (dead_cp) + { + cp = dead_cp; + goto Initialize; + } } if (child_proc_count == MAX_CHILDREN) return NULL; @@ -1002,12 +1017,24 @@ reader_thread (void *arg) if (cp->status == STATUS_READ_ERROR || !cp->char_avail) break; + if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess && cp->fd >= 0) + { + /* Somebody already called delete_child on this child, since + only delete_child zeroes out cp->char_avail. This means + no one will read from cp->fd and will not set the + FILE_AT_EOF flag, therefore preventing sys_select from + noticing that the process died. Set the flag here + instead. */ + fd_info[cp->fd].flags |= FILE_AT_EOF; + } + /* The name char_avail is a misnomer - it really just means the read-ahead has completed, whether successfully or not. */ if (!SetEvent (cp->char_avail)) { - DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n", - GetLastError (), cp->fd)); + DebPrint (("reader_thread.SetEvent(0x%x) failed with %lu for fd %ld (PID %d)\n", + (DWORD_PTR)cp->char_avail, GetLastError (), + cp->fd, cp->pid)); return 1; } @@ -1210,6 +1237,11 @@ reap_subprocess (child_process *cp) sys_read when the subprocess output is fully read. */ if (cp->fd < 0) delete_child (cp); + else + { + /* Reset the flag set by reader_thread. */ + fd_info[cp->fd].flags &= ~FILE_AT_EOF; + } } /* Wait for a child process specified by PID, or for any of our @@ -2035,7 +2067,7 @@ count_children: /* Some child_procs might be sockets; ignore them. Also some children may have died already, but we haven't finished reading the process output; ignore them too. */ - if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess + if ((CHILD_ACTIVE (cp) || cp->procinfo.hProcess) && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) |