aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2015-03-27 12:44:31 +0300
committerEli Zaretskii2015-03-27 12:44:31 +0300
commitd133cf839421462280ac0bfd9bd84c591f0e0249 (patch)
treed964223f8da827058aece69ed66ca25ba82ebbf4 /src
parent792d44b3c31d2a682607ab8b79ae7d26b7402f41 (diff)
downloademacs-d133cf839421462280ac0bfd9bd84c591f0e0249.tar.gz
emacs-d133cf839421462280ac0bfd9bd84c591f0e0249.zip
Support non-blocking connect on MS-Windows (Bug#20207)
Based on ideas from Kim F. Storm <storm@cua.dk>, see http://lists.gnu.org/archive/html/emacs-devel/2006-12/msg00873.html. src/w32proc.c (reader_thread): If the FILE_CONNECT flag is set, call '_sys_wait_connect'. If it returns STATUS_CONNECT_FAILED, exit the thread with code 2. (sys_select): Support 'wfds' in addition to 'rfds'. If a descriptor in 'wfds' has its bit set, but the corresponding fd_info member doesn't have its FILE_CONNECT flag set, ignore the descriptor. Otherwise, acknowledge a successful non-blocking connect by resetting the FILE_CONNECT flag and setting cp->status to STATUS_READ_ACKNOWLEDGED. src/w32.h (STATUS_CONNECT_FAILED): New enumeration value. (struct _child_process): New member 'errcode'. (FILE_CONNECT): New flag. (_sys_wait_connect): Add prototype. src/w32.c (pfn_WSAEnumNetworkEvents): New function pointer. (init_winsock): Load WSAEnumNetworkEvents from winsock DLL. (set_errno): Map WSAEWOULDBLOCK and WSAENOTCONN. (sys_connect): Support non-blocking 'connect' calls by setting the FILE_CONNECT flag in the fd_info member and returning EINPROGRESS. (_sys_read_ahead): Add debug message if this function is called for a descriptor that waits for a non-blocking connect to complete. (_sys_wait_connect): New function. (sys_read): Support STATUS_CONNECT_FAILED. Return the error code recorded by _sys_wait_connect when the non-blocking connect failed. Don't call WSAGetLastError before a call to set_errno had a chance to use its value, since WSAGetLastError clears the last error. nt/inc/ms-w32.h (BROKEN_NON_BLOCKING_CONNECT): Don't define.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog35
-rw-r--r--src/w32.c105
-rw-r--r--src/w32.h9
-rw-r--r--src/w32proc.c77
4 files changed, 204 insertions, 22 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 632b798ce08..67e04f6f41c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,38 @@
12015-03-27 Eli Zaretskii <eliz@gnu.org>
2
3 Support non-blocking connect on MS-Windows.
4 Based on ideas from Kim F. Storm <storm@cua.dk>, see
5 http://lists.gnu.org/archive/html/emacs-devel/2006-12/msg00873.html.
6
7 * w32proc.c (reader_thread): If the FILE_CONNECT flag is set, call
8 '_sys_wait_connect'. If it returns STATUS_CONNECT_FAILED, exit
9 the thread with code 2.
10 (sys_select): Support 'wfds' in addition to 'rfds'. If a
11 descriptor in 'wfds' has its bit set, but the corresponding
12 fd_info member doesn't have its FILE_CONNECT flag set, ignore the
13 descriptor. Otherwise, acknowledge a successful non-blocking
14 connect by resetting the FILE_CONNECT flag and setting cp->status
15 to STATUS_READ_ACKNOWLEDGED. (Bug#20207)
16
17 * w32.h (STATUS_CONNECT_FAILED): New enumeration value.
18 (struct _child_process): New member 'errcode'.
19 (FILE_CONNECT): New flag.
20 (_sys_wait_connect): Add prototype.
21
22 * w32.c (pfn_WSAEnumNetworkEvents): New function pointer.
23 (init_winsock): Load WSAEnumNetworkEvents from winsock DLL.
24 (set_errno): Map WSAEWOULDBLOCK and WSAENOTCONN.
25 (sys_connect): Support non-blocking 'connect' calls by setting the
26 FILE_CONNECT flag in the fd_info member and returning EINPROGRESS.
27 (_sys_read_ahead): Add debug message if this function is called
28 for a descriptor that waits for a non-blocking connect to complete.
29 (_sys_wait_connect): New function.
30 (sys_read): Support STATUS_CONNECT_FAILED. Return the error code
31 recorded by _sys_wait_connect when the non-blocking connect
32 failed. Don't call WSAGetLastError before a call to set_errno had
33 a chance to use its value, since WSAGetLastError clears the last
34 error.
35
12015-03-25 Stefan Monnier <monnier@iro.umontreal.ca> 362015-03-25 Stefan Monnier <monnier@iro.umontreal.ca>
2 37
3 * editfns.c (save_excursion_save): Don't save the mark. 38 * editfns.c (save_excursion_save): Don't save the mark.
diff --git a/src/w32.c b/src/w32.c
index 547db0f6dd9..1917fea343d 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -7038,6 +7038,9 @@ int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
7038void (PASCAL *pfn_WSASetLastError) (int iError); 7038void (PASCAL *pfn_WSASetLastError) (int iError);
7039int (PASCAL *pfn_WSAGetLastError) (void); 7039int (PASCAL *pfn_WSAGetLastError) (void);
7040int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents); 7040int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
7041int (PASCAL *pfn_WSAEnumNetworkEvents) (SOCKET s, HANDLE hEventObject,
7042 WSANETWORKEVENTS *NetworkEvents);
7043
7041HANDLE (PASCAL *pfn_WSACreateEvent) (void); 7044HANDLE (PASCAL *pfn_WSACreateEvent) (void);
7042int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent); 7045int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
7043int (PASCAL *pfn_socket) (int af, int type, int protocol); 7046int (PASCAL *pfn_socket) (int af, int type, int protocol);
@@ -7123,6 +7126,7 @@ init_winsock (int load_now)
7123 LOAD_PROC (WSASetLastError); 7126 LOAD_PROC (WSASetLastError);
7124 LOAD_PROC (WSAGetLastError); 7127 LOAD_PROC (WSAGetLastError);
7125 LOAD_PROC (WSAEventSelect); 7128 LOAD_PROC (WSAEventSelect);
7129 LOAD_PROC (WSAEnumNetworkEvents);
7126 LOAD_PROC (WSACreateEvent); 7130 LOAD_PROC (WSACreateEvent);
7127 LOAD_PROC (WSACloseEvent); 7131 LOAD_PROC (WSACloseEvent);
7128 LOAD_PROC (socket); 7132 LOAD_PROC (socket);
@@ -7206,6 +7210,8 @@ set_errno (void)
7206 case WSAEMFILE: errno = EMFILE; break; 7210 case WSAEMFILE: errno = EMFILE; break;
7207 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break; 7211 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
7208 case WSAENOTEMPTY: errno = ENOTEMPTY; break; 7212 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
7213 case WSAEWOULDBLOCK: errno = EWOULDBLOCK; break;
7214 case WSAENOTCONN: errno = ENOTCONN; break;
7209 default: errno = wsa_err; break; 7215 default: errno = wsa_err; break;
7210 } 7216 }
7211} 7217}
@@ -7473,8 +7479,18 @@ sys_connect (int s, const struct sockaddr * name, int namelen)
7473 { 7479 {
7474 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen); 7480 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
7475 if (rc == SOCKET_ERROR) 7481 if (rc == SOCKET_ERROR)
7476 set_errno (); 7482 {
7477 return rc; 7483 set_errno ();
7484 /* If this is a non-blocking 'connect', set the bit in flags
7485 that will tell reader_thread to wait for connection
7486 before trying to read. */
7487 if (errno == EWOULDBLOCK && (fd_info[s].flags & FILE_NDELAY) != 0)
7488 {
7489 errno = EINPROGRESS; /* that's what process.c expects */
7490 fd_info[s].flags |= FILE_CONNECT;
7491 }
7492 return rc;
7493 }
7478 } 7494 }
7479 errno = ENOTSOCK; 7495 errno = ENOTSOCK;
7480 return SOCKET_ERROR; 7496 return SOCKET_ERROR;
@@ -7984,6 +8000,8 @@ _sys_read_ahead (int fd)
7984 emacs_abort (); 8000 emacs_abort ();
7985 } 8001 }
7986 8002
8003 if ((fd_info[fd].flags & FILE_CONNECT) != 0)
8004 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd));
7987 cp->status = STATUS_READ_IN_PROGRESS; 8005 cp->status = STATUS_READ_IN_PROGRESS;
7988 8006
7989 if (fd_info[fd].flags & FILE_PIPE) 8007 if (fd_info[fd].flags & FILE_PIPE)
@@ -8106,6 +8124,60 @@ _sys_wait_accept (int fd)
8106} 8124}
8107 8125
8108int 8126int
8127_sys_wait_connect (int fd)
8128{
8129 HANDLE hEv;
8130 child_process * cp;
8131 int rc;
8132
8133 if (fd < 0 || fd >= MAXDESC)
8134 return STATUS_READ_ERROR;
8135
8136 cp = fd_info[fd].cp;
8137 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8138 return STATUS_READ_ERROR;
8139
8140 cp->status = STATUS_READ_FAILED;
8141
8142 hEv = pfn_WSACreateEvent ();
8143 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_CONNECT);
8144 if (rc != SOCKET_ERROR)
8145 {
8146 do {
8147 rc = WaitForSingleObject (hEv, 500);
8148 Sleep (5);
8149 } while (rc == WAIT_TIMEOUT
8150 && cp->status != STATUS_READ_ERROR
8151 && cp->char_avail);
8152 if (rc == WAIT_OBJECT_0)
8153 {
8154 /* We've got an event, but it could be a successful
8155 connection, or it could be a failure. Find out
8156 which one is it. */
8157 WSANETWORKEVENTS events;
8158
8159 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd), hEv, &events);
8160 if ((events.lNetworkEvents & FD_CONNECT) != 0
8161 && events.iErrorCode[FD_CONNECT_BIT])
8162 {
8163 cp->status = STATUS_CONNECT_FAILED;
8164 cp->errcode = events.iErrorCode[FD_CONNECT_BIT];
8165 }
8166 else
8167 {
8168 cp->status = STATUS_READ_SUCCEEDED;
8169 cp->errcode = 0;
8170 }
8171 }
8172 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8173 }
8174 else
8175 pfn_WSACloseEvent (hEv);
8176
8177 return cp->status;
8178}
8179
8180int
8109sys_read (int fd, char * buffer, unsigned int count) 8181sys_read (int fd, char * buffer, unsigned int count)
8110{ 8182{
8111 int nchars; 8183 int nchars;
@@ -8174,6 +8246,7 @@ sys_read (int fd, char * buffer, unsigned int count)
8174 ResetEvent (cp->char_avail); 8246 ResetEvent (cp->char_avail);
8175 8247
8176 case STATUS_READ_ACKNOWLEDGED: 8248 case STATUS_READ_ACKNOWLEDGED:
8249 case STATUS_CONNECT_FAILED:
8177 break; 8250 break;
8178 8251
8179 default: 8252 default:
@@ -8239,7 +8312,29 @@ sys_read (int fd, char * buffer, unsigned int count)
8239 { 8312 {
8240 if (winsock_lib == NULL) emacs_abort (); 8313 if (winsock_lib == NULL) emacs_abort ();
8241 8314
8242 /* do the equivalent of a non-blocking read */ 8315 /* When a non-blocking 'connect' call fails,
8316 wait_reading_process_output detects this by calling
8317 'getpeername', and then attempts to obtain the connection
8318 error code by trying to read 1 byte from the socket. If
8319 we try to serve that read by calling 'recv' below, the
8320 error we get is a generic WSAENOTCONN, not the actual
8321 connection error. So instead, we use the actual error
8322 code stashed by '_sys_wait_connect' in cp->errcode.
8323 Alternatively, we could have used 'getsockopt', like on
8324 GNU/Linux, but: (a) I have no idea whether the winsock
8325 version could hang, as it does "on some systems" (see the
8326 comment in process.c); and (b) 'getsockopt' on Windows is
8327 documented to clear the socket error for the entire
8328 process, which I'm not sure is TRT; FIXME. */
8329 if (current_status == STATUS_CONNECT_FAILED
8330 && (fd_info[fd].flags & FILE_CONNECT) != 0
8331 && cp->errcode != 0)
8332 {
8333 pfn_WSASetLastError (cp->errcode);
8334 set_errno ();
8335 return -1;
8336 }
8337 /* Do the equivalent of a non-blocking read. */
8243 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting); 8338 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
8244 if (waiting == 0 && nchars == 0) 8339 if (waiting == 0 && nchars == 0)
8245 { 8340 {
@@ -8253,9 +8348,9 @@ sys_read (int fd, char * buffer, unsigned int count)
8253 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0); 8348 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
8254 if (res == SOCKET_ERROR) 8349 if (res == SOCKET_ERROR)
8255 { 8350 {
8256 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8257 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
8258 set_errno (); 8351 set_errno ();
8352 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8353 errno, SOCK_HANDLE (fd)));
8259 return -1; 8354 return -1;
8260 } 8355 }
8261 nchars += res; 8356 nchars += res;
diff --git a/src/w32.h b/src/w32.h
index 835557d5ec7..9b3521d077f 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -61,7 +61,8 @@ enum {
61 STATUS_READ_IN_PROGRESS, 61 STATUS_READ_IN_PROGRESS,
62 STATUS_READ_FAILED, 62 STATUS_READ_FAILED,
63 STATUS_READ_SUCCEEDED, 63 STATUS_READ_SUCCEEDED,
64 STATUS_READ_ACKNOWLEDGED 64 STATUS_READ_ACKNOWLEDGED,
65 STATUS_CONNECT_FAILED
65}; 66};
66 67
67/* This structure is used for both pipes and sockets; for 68/* This structure is used for both pipes and sockets; for
@@ -96,6 +97,8 @@ typedef struct _child_process
96 /* Status of subprocess/connection and of reading its output. For 97 /* Status of subprocess/connection and of reading its output. For
97 values, see the enumeration above. */ 98 values, see the enumeration above. */
98 volatile int status; 99 volatile int status;
100 /* Used to store errno value of failed async 'connect' calls. */
101 volatile int errcode;
99 /* Holds a single character read by _sys_read_ahead, when a 102 /* Holds a single character read by _sys_read_ahead, when a
100 subprocess has some output ready. */ 103 subprocess has some output ready. */
101 char chr; 104 char chr;
@@ -122,7 +125,8 @@ extern filedesc fd_info [ MAXDESC ];
122/* fd_info flag definitions */ 125/* fd_info flag definitions */
123#define FILE_READ 0x0001 126#define FILE_READ 0x0001
124#define FILE_WRITE 0x0002 127#define FILE_WRITE 0x0002
125#define FILE_LISTEN 0x0004 128#define FILE_LISTEN 0x0004
129#define FILE_CONNECT 0x0008
126#define FILE_BINARY 0x0010 130#define FILE_BINARY 0x0010
127#define FILE_LAST_CR 0x0020 131#define FILE_LAST_CR 0x0020
128#define FILE_AT_EOF 0x0040 132#define FILE_AT_EOF 0x0040
@@ -171,6 +175,7 @@ extern void init_timers (void);
171 175
172extern int _sys_read_ahead (int fd); 176extern int _sys_read_ahead (int fd);
173extern int _sys_wait_accept (int fd); 177extern int _sys_wait_accept (int fd);
178extern int _sys_wait_connect (int fd);
174 179
175extern HMODULE w32_delayed_load (Lisp_Object); 180extern HMODULE w32_delayed_load (Lisp_Object);
176 181
diff --git a/src/w32proc.c b/src/w32proc.c
index 74731db2426..2d10534aa47 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -1011,7 +1011,9 @@ reader_thread (void *arg)
1011 { 1011 {
1012 int rc; 1012 int rc;
1013 1013
1014 if (cp->fd >= 0 && fd_info[cp->fd].flags & FILE_LISTEN) 1014 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_CONNECT) != 0)
1015 rc = _sys_wait_connect (cp->fd);
1016 else if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_LISTEN) != 0)
1015 rc = _sys_wait_accept (cp->fd); 1017 rc = _sys_wait_accept (cp->fd);
1016 else 1018 else
1017 rc = _sys_read_ahead (cp->fd); 1019 rc = _sys_read_ahead (cp->fd);
@@ -1031,8 +1033,8 @@ reader_thread (void *arg)
1031 return 1; 1033 return 1;
1032 } 1034 }
1033 1035
1034 if (rc == STATUS_READ_ERROR) 1036 if (rc == STATUS_READ_ERROR || rc == STATUS_CONNECT_FAILED)
1035 return 1; 1037 return 2;
1036 1038
1037 /* If the read died, the child has died so let the thread die */ 1039 /* If the read died, the child has died so let the thread die */
1038 if (rc == STATUS_READ_FAILED) 1040 if (rc == STATUS_READ_FAILED)
@@ -1929,7 +1931,7 @@ int
1929sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, 1931sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1930 struct timespec *timeout, void *ignored) 1932 struct timespec *timeout, void *ignored)
1931{ 1933{
1932 SELECT_TYPE orfds; 1934 SELECT_TYPE orfds, owfds;
1933 DWORD timeout_ms, start_time; 1935 DWORD timeout_ms, start_time;
1934 int i, nh, nc, nr; 1936 int i, nh, nc, nr;
1935 DWORD active; 1937 DWORD active;
@@ -1947,15 +1949,27 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1947 return 0; 1949 return 0;
1948 } 1950 }
1949 1951
1950 /* Otherwise, we only handle rfds, so fail otherwise. */ 1952 /* Otherwise, we only handle rfds and wfds, so fail otherwise. */
1951 if (rfds == NULL || wfds != NULL || efds != NULL) 1953 if ((rfds == NULL && wfds == NULL) || efds != NULL)
1952 { 1954 {
1953 errno = EINVAL; 1955 errno = EINVAL;
1954 return -1; 1956 return -1;
1955 } 1957 }
1956 1958
1957 orfds = *rfds; 1959 if (rfds)
1958 FD_ZERO (rfds); 1960 {
1961 orfds = *rfds;
1962 FD_ZERO (rfds);
1963 }
1964 else
1965 FD_ZERO (&orfds);
1966 if (wfds)
1967 {
1968 owfds = *wfds;
1969 FD_ZERO (wfds);
1970 }
1971 else
1972 FD_ZERO (&owfds);
1959 nr = 0; 1973 nr = 0;
1960 1974
1961 /* If interrupt_handle is available and valid, always wait on it, to 1975 /* If interrupt_handle is available and valid, always wait on it, to
@@ -1970,7 +1984,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1970 1984
1971 /* Build a list of pipe handles to wait on. */ 1985 /* Build a list of pipe handles to wait on. */
1972 for (i = 0; i < nfds; i++) 1986 for (i = 0; i < nfds; i++)
1973 if (FD_ISSET (i, &orfds)) 1987 if (FD_ISSET (i, &orfds) || FD_ISSET (i, &owfds))
1974 { 1988 {
1975 if (i == 0) 1989 if (i == 0)
1976 { 1990 {
@@ -1984,7 +1998,7 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1984 1998
1985 /* Check for any emacs-generated input in the queue since 1999 /* Check for any emacs-generated input in the queue since
1986 it won't be detected in the wait */ 2000 it won't be detected in the wait */
1987 if (detect_input_pending ()) 2001 if (rfds && detect_input_pending ())
1988 { 2002 {
1989 FD_SET (i, rfds); 2003 FD_SET (i, rfds);
1990 return 1; 2004 return 1;
@@ -1999,6 +2013,13 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
1999 { 2013 {
2000 /* Child process and socket/comm port input. */ 2014 /* Child process and socket/comm port input. */
2001 cp = fd_info[i].cp; 2015 cp = fd_info[i].cp;
2016 if (FD_ISSET (i, &owfds)
2017 && cp
2018 && (fd_info[i].flags && FILE_CONNECT) == 0)
2019 {
2020 DebPrint (("sys_select: fd %d is in wfds, but FILE_CONNECT is reset!\n", i));
2021 cp = NULL;
2022 }
2002 if (cp) 2023 if (cp)
2003 { 2024 {
2004 int current_status = cp->status; 2025 int current_status = cp->status;
@@ -2007,6 +2028,8 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
2007 { 2028 {
2008 /* Tell reader thread which file handle to use. */ 2029 /* Tell reader thread which file handle to use. */
2009 cp->fd = i; 2030 cp->fd = i;
2031 /* Zero out the error code. */
2032 cp->errcode = 0;
2010 /* Wake up the reader thread for this process */ 2033 /* Wake up the reader thread for this process */
2011 cp->status = STATUS_READ_READY; 2034 cp->status = STATUS_READ_READY;
2012 if (!SetEvent (cp->char_consumed)) 2035 if (!SetEvent (cp->char_consumed))
@@ -2197,7 +2220,7 @@ count_children:
2197 2220
2198 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0) 2221 if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0)
2199 fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD; 2222 fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD;
2200 /* SIG_DFL for SIGCHLD is ignore */ 2223 /* SIG_DFL for SIGCHLD is ignored */
2201 else if (sig_handlers[SIGCHLD] != SIG_DFL && 2224 else if (sig_handlers[SIGCHLD] != SIG_DFL &&
2202 sig_handlers[SIGCHLD] != SIG_IGN) 2225 sig_handlers[SIGCHLD] != SIG_IGN)
2203 { 2226 {
@@ -2214,7 +2237,7 @@ count_children:
2214 errno = EINTR; 2237 errno = EINTR;
2215 return -1; 2238 return -1;
2216 } 2239 }
2217 else if (fdindex[active] == 0) 2240 else if (rfds && fdindex[active] == 0)
2218 { 2241 {
2219 /* Keyboard input available */ 2242 /* Keyboard input available */
2220 FD_SET (0, rfds); 2243 FD_SET (0, rfds);
@@ -2222,9 +2245,33 @@ count_children:
2222 } 2245 }
2223 else 2246 else
2224 { 2247 {
2225 /* must be a socket or pipe - read ahead should have 2248 /* Must be a socket or pipe - read ahead should have
2226 completed, either succeeding or failing. */ 2249 completed, either succeeding or failing. If this handle
2227 FD_SET (fdindex[active], rfds); 2250 was waiting for an async 'connect', reset the connect
2251 flag, so it could read from now on. */
2252 if (wfds && (fd_info[fdindex[active]].flags & FILE_CONNECT) != 0)
2253 {
2254 cp = fd_info[fdindex[active]].cp;
2255 if (cp)
2256 {
2257 /* Don't reset the FILE_CONNECT bit and don't
2258 acknowledge the read if the status is
2259 STATUS_CONNECT_FAILED or some other
2260 failure. That's because the thread exits in those
2261 cases, so it doesn't need the ACK, and we want to
2262 keep the FILE_CONNECT bit as evidence that the
2263 connect failed, to be checked in sys_read. */
2264 if (cp->status == STATUS_READ_SUCCEEDED)
2265 {
2266 fd_info[cp->fd].flags &= ~FILE_CONNECT;
2267 cp->status = STATUS_READ_ACKNOWLEDGED;
2268 }
2269 ResetEvent (cp->char_avail);
2270 }
2271 FD_SET (fdindex[active], wfds);
2272 }
2273 else if (rfds)
2274 FD_SET (fdindex[active], rfds);
2228 nr++; 2275 nr++;
2229 } 2276 }
2230 2277