diff options
author | Ron Yorston <rmy@pobox.com> | 2018-02-13 13:11:57 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-02-13 13:11:57 +0000 |
commit | 054a022f7c9a5cdf5ed44ffcf48e214a5b11c913 (patch) | |
tree | 649c2cd9e4e8866366eeccafc1891a785a1db03f | |
parent | 8bc8da2577c0f0c3b4f33b3190de57a2b4d13a24 (diff) | |
download | busybox-w32-054a022f7c9a5cdf5ed44ffcf48e214a5b11c913.tar.gz busybox-w32-054a022f7c9a5cdf5ed44ffcf48e214a5b11c913.tar.bz2 busybox-w32-054a022f7c9a5cdf5ed44ffcf48e214a5b11c913.zip |
win32: update poll implementation to match latest gnulib version
-rw-r--r-- | win32/poll.c | 416 |
1 files changed, 207 insertions, 209 deletions
diff --git a/win32/poll.c b/win32/poll.c index 935b92423..3294fdc96 100644 --- a/win32/poll.c +++ b/win32/poll.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Emulation for poll(2) | 1 | /* Emulation for poll(2) |
2 | Contributed by Paolo Bonzini. | 2 | Contributed by Paolo Bonzini. |
3 | 3 | ||
4 | Copyright 2001-2003, 2006-2011 Free Software Foundation, Inc. | 4 | Copyright 2001-2003, 2006-2018 Free Software Foundation, Inc. |
5 | 5 | ||
6 | This file is part of gnulib. | 6 | This file is part of gnulib. |
7 | 7 | ||
@@ -16,8 +16,7 @@ | |||
16 | GNU General Public License for more details. | 16 | GNU General Public License for more details. |
17 | 17 | ||
18 | You should have received a copy of the GNU General Public License along | 18 | You should have received a copy of the GNU General Public License along |
19 | with this program; if not, write to the Free Software Foundation, | 19 | with this program; if not, see <https://www.gnu.org/licenses/>. */ |
20 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
21 | 20 | ||
22 | /* Tell gcc not to warn about the (nfd < 0) tests, below. */ | 21 | /* Tell gcc not to warn about the (nfd < 0) tests, below. */ |
23 | #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ | 22 | #if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__ |
@@ -36,6 +35,7 @@ | |||
36 | #include <assert.h> | 35 | #include <assert.h> |
37 | 36 | ||
38 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | 37 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
38 | # define WINDOWS_NATIVE | ||
39 | # define WIN32_NATIVE | 39 | # define WIN32_NATIVE |
40 | # if defined (_MSC_VER) | 40 | # if defined (_MSC_VER) |
41 | # define _WIN32_WINNT 0x0502 | 41 | # define _WIN32_WINNT 0x0502 |
@@ -47,11 +47,12 @@ | |||
47 | # include <conio.h> | 47 | # include <conio.h> |
48 | #else | 48 | #else |
49 | # include <sys/time.h> | 49 | # include <sys/time.h> |
50 | # include <sys/socket.h> | ||
51 | # include <sys/select.h> | ||
52 | # include <unistd.h> | 50 | # include <unistd.h> |
53 | #endif | 51 | #endif |
54 | 52 | ||
53 | #include <sys/select.h> | ||
54 | #include <sys/socket.h> | ||
55 | |||
55 | #ifdef HAVE_SYS_IOCTL_H | 56 | #ifdef HAVE_SYS_IOCTL_H |
56 | # include <sys/ioctl.h> | 57 | # include <sys/ioctl.h> |
57 | #endif | 58 | #endif |
@@ -70,9 +71,21 @@ | |||
70 | # define MSG_PEEK 0 | 71 | # define MSG_PEEK 0 |
71 | #endif | 72 | #endif |
72 | 73 | ||
73 | #ifdef WIN32_NATIVE | 74 | #ifdef WINDOWS_NATIVE |
75 | |||
76 | /* Here we need the recv() function from Windows, that takes a SOCKET as | ||
77 | first argument, not any possible gnulib override. */ | ||
78 | # undef recv | ||
74 | 79 | ||
75 | #define IsConsoleHandle(h) (((intptr_t) (h) & 3) == 3) | 80 | /* Here we need the select() function from Windows, because we pass bit masks |
81 | of SOCKETs, not bit masks of FDs. */ | ||
82 | # undef select | ||
83 | |||
84 | static BOOL IsConsoleHandle (HANDLE h) | ||
85 | { | ||
86 | DWORD mode; | ||
87 | return GetConsoleMode (h, &mode) != 0; | ||
88 | } | ||
76 | 89 | ||
77 | static BOOL | 90 | static BOOL |
78 | IsSocketHandle (HANDLE h) | 91 | IsSocketHandle (HANDLE h) |
@@ -117,7 +130,7 @@ typedef enum _FILE_INFORMATION_CLASS { | |||
117 | } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; | 130 | } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; |
118 | 131 | ||
119 | typedef DWORD (WINAPI *PNtQueryInformationFile) | 132 | typedef DWORD (WINAPI *PNtQueryInformationFile) |
120 | (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS); | 133 | (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS); |
121 | 134 | ||
122 | # ifndef PIPE_BUF | 135 | # ifndef PIPE_BUF |
123 | # define PIPE_BUF 512 | 136 | # define PIPE_BUF 512 |
@@ -127,7 +140,7 @@ typedef DWORD (WINAPI *PNtQueryInformationFile) | |||
127 | for the handle, eliminate them from *P_SOUGHT. */ | 140 | for the handle, eliminate them from *P_SOUGHT. */ |
128 | 141 | ||
129 | static int | 142 | static int |
130 | win32_compute_revents (HANDLE h, int *p_sought) | 143 | windows_compute_revents (HANDLE h, int *p_sought) |
131 | { | 144 | { |
132 | int i, ret, happened; | 145 | int i, ret, happened; |
133 | INPUT_RECORD *irbuffer; | 146 | INPUT_RECORD *irbuffer; |
@@ -142,81 +155,82 @@ win32_compute_revents (HANDLE h, int *p_sought) | |||
142 | { | 155 | { |
143 | case FILE_TYPE_PIPE: | 156 | case FILE_TYPE_PIPE: |
144 | if (!once_only) | 157 | if (!once_only) |
145 | { | 158 | { |
146 | NtQueryInformationFile = (PNtQueryInformationFile) | 159 | NtQueryInformationFile = (PNtQueryInformationFile) |
147 | GetProcAddress (GetModuleHandle ("ntdll.dll"), | 160 | GetProcAddress (GetModuleHandle ("ntdll.dll"), |
148 | "NtQueryInformationFile"); | 161 | "NtQueryInformationFile"); |
149 | once_only = TRUE; | 162 | once_only = TRUE; |
150 | } | 163 | } |
151 | 164 | ||
152 | happened = 0; | 165 | happened = 0; |
153 | if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0) | 166 | if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0) |
154 | { | 167 | { |
155 | if (avail) | 168 | if (avail) |
156 | happened |= *p_sought & (POLLIN | POLLRDNORM); | 169 | happened |= *p_sought & (POLLIN | POLLRDNORM); |
157 | } | 170 | } |
158 | else if (GetLastError () == ERROR_BROKEN_PIPE) | 171 | else if (GetLastError () == ERROR_BROKEN_PIPE) |
159 | happened |= POLLHUP; | 172 | happened |= POLLHUP; |
160 | 173 | ||
161 | else | 174 | else |
162 | { | 175 | { |
163 | /* It was the write-end of the pipe. Check if it is writable. | 176 | /* It was the write-end of the pipe. Check if it is writable. |
164 | If NtQueryInformationFile fails, optimistically assume the pipe is | 177 | If NtQueryInformationFile fails, optimistically assume the pipe is |
165 | writable. This could happen on Win9x, where NtQueryInformationFile | 178 | writable. This could happen on Windows 9x, where |
166 | is not available, or if we inherit a pipe that doesn't permit | 179 | NtQueryInformationFile is not available, or if we inherit a pipe |
167 | FILE_READ_ATTRIBUTES access on the write end (I think this should | 180 | that doesn't permit FILE_READ_ATTRIBUTES access on the write end |
168 | not happen since WinXP SP2; WINE seems fine too). Otherwise, | 181 | (I think this should not happen since Windows XP SP2; WINE seems |
169 | ensure that enough space is available for atomic writes. */ | 182 | fine too). Otherwise, ensure that enough space is available for |
170 | memset (&iosb, 0, sizeof (iosb)); | 183 | atomic writes. */ |
171 | memset (&fpli, 0, sizeof (fpli)); | 184 | memset (&iosb, 0, sizeof (iosb)); |
172 | 185 | memset (&fpli, 0, sizeof (fpli)); | |
173 | if (!NtQueryInformationFile | 186 | |
174 | || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), | 187 | if (!NtQueryInformationFile |
175 | FilePipeLocalInformation) | 188 | || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), |
176 | || fpli.WriteQuotaAvailable >= PIPE_BUF | 189 | FilePipeLocalInformation) |
177 | || (fpli.OutboundQuota < PIPE_BUF && | 190 | || fpli.WriteQuotaAvailable >= PIPE_BUF |
178 | fpli.WriteQuotaAvailable == fpli.OutboundQuota)) | 191 | || (fpli.OutboundQuota < PIPE_BUF && |
179 | happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | 192 | fpli.WriteQuotaAvailable == fpli.OutboundQuota)) |
180 | } | 193 | happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); |
194 | } | ||
181 | return happened; | 195 | return happened; |
182 | 196 | ||
183 | case FILE_TYPE_CHAR: | 197 | case FILE_TYPE_CHAR: |
184 | ret = WaitForSingleObject (h, 0); | 198 | ret = WaitForSingleObject (h, 0); |
185 | if (!IsConsoleHandle (h)) | 199 | if (!IsConsoleHandle (h)) |
186 | return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0; | 200 | return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0; |
187 | 201 | ||
188 | nbuffer = avail = 0; | 202 | nbuffer = avail = 0; |
189 | bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); | 203 | bRet = GetNumberOfConsoleInputEvents (h, &nbuffer); |
190 | if (bRet) | 204 | if (bRet) |
191 | { | 205 | { |
192 | /* Input buffer. */ | 206 | /* Input buffer. */ |
193 | *p_sought &= POLLIN | POLLRDNORM; | 207 | *p_sought &= POLLIN | POLLRDNORM; |
194 | if (nbuffer == 0) | 208 | if (nbuffer == 0) |
195 | return POLLHUP; | 209 | return POLLHUP; |
196 | if (!*p_sought) | 210 | if (!*p_sought) |
197 | return 0; | 211 | return 0; |
198 | 212 | ||
199 | irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); | 213 | irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD)); |
200 | bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); | 214 | bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail); |
201 | if (!bRet || avail == 0) | 215 | if (!bRet || avail == 0) |
202 | return POLLHUP; | 216 | return POLLHUP; |
203 | 217 | ||
204 | for (i = 0; i < avail; i++) | 218 | for (i = 0; i < avail; i++) |
205 | if (irbuffer[i].EventType == KEY_EVENT) | 219 | if (irbuffer[i].EventType == KEY_EVENT) |
206 | return *p_sought; | 220 | return *p_sought; |
207 | return 0; | 221 | return 0; |
208 | } | 222 | } |
209 | else | 223 | else |
210 | { | 224 | { |
211 | /* Screen buffer. */ | 225 | /* Screen buffer. */ |
212 | *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND; | 226 | *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND; |
213 | return *p_sought; | 227 | return *p_sought; |
214 | } | 228 | } |
215 | 229 | ||
216 | default: | 230 | default: |
217 | ret = WaitForSingleObject (h, 0); | 231 | ret = WaitForSingleObject (h, 0); |
218 | if (ret == WAIT_OBJECT_0) | 232 | if (ret == WAIT_OBJECT_0) |
219 | return *p_sought & ~(POLLPRI | POLLRDBAND); | 233 | return *p_sought & ~(POLLPRI | POLLRDBAND); |
220 | 234 | ||
221 | return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); | 235 | return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND); |
222 | } | 236 | } |
@@ -225,7 +239,7 @@ win32_compute_revents (HANDLE h, int *p_sought) | |||
225 | /* Convert fd_sets returned by select into revents values. */ | 239 | /* Convert fd_sets returned by select into revents values. */ |
226 | 240 | ||
227 | static int | 241 | static int |
228 | win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents) | 242 | windows_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents) |
229 | { | 243 | { |
230 | int happened = 0; | 244 | int happened = 0; |
231 | 245 | ||
@@ -243,15 +257,15 @@ win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents) | |||
243 | WSASetLastError (0); | 257 | WSASetLastError (0); |
244 | 258 | ||
245 | if (r > 0 || error == WSAENOTCONN) | 259 | if (r > 0 || error == WSAENOTCONN) |
246 | happened |= (POLLIN | POLLRDNORM) & sought; | 260 | happened |= (POLLIN | POLLRDNORM) & sought; |
247 | 261 | ||
248 | /* Distinguish hung-up sockets from other errors. */ | 262 | /* Distinguish hung-up sockets from other errors. */ |
249 | else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET | 263 | else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET |
250 | || error == WSAECONNABORTED || error == WSAENETRESET) | 264 | || error == WSAECONNABORTED || error == WSAENETRESET) |
251 | happened |= POLLHUP; | 265 | happened |= POLLHUP; |
252 | 266 | ||
253 | else | 267 | else |
254 | happened |= POLLERR; | 268 | happened |= POLLERR; |
255 | } | 269 | } |
256 | 270 | ||
257 | if (lNetworkEvents & (FD_WRITE | FD_CONNECT)) | 271 | if (lNetworkEvents & (FD_WRITE | FD_CONNECT)) |
@@ -277,33 +291,37 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds) | |||
277 | 291 | ||
278 | # if defined __MACH__ && defined __APPLE__ | 292 | # if defined __MACH__ && defined __APPLE__ |
279 | /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK | 293 | /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK |
280 | for some kinds of descriptors. Detect if this descriptor is a | 294 | for some kinds of descriptors. Detect if this descriptor is a |
281 | connected socket, a server socket, or something else using a | 295 | connected socket, a server socket, or something else using a |
282 | 0-byte recv, and use ioctl(2) to detect POLLHUP. */ | 296 | 0-byte recv, and use ioctl(2) to detect POLLHUP. */ |
283 | r = recv (fd, NULL, 0, MSG_PEEK); | 297 | r = recv (fd, NULL, 0, MSG_PEEK); |
284 | socket_errno = (r < 0) ? errno : 0; | 298 | socket_errno = (r < 0) ? errno : 0; |
285 | if (r == 0 || socket_errno == ENOTSOCK) | 299 | if (r == 0 || socket_errno == ENOTSOCK) |
286 | ioctl (fd, FIONREAD, &r); | 300 | ioctl (fd, FIONREAD, &r); |
287 | # else | 301 | # else |
288 | char data[64]; | 302 | char data[64]; |
289 | r = recv (fd, data, sizeof (data), MSG_PEEK); | 303 | r = recv (fd, data, sizeof (data), MSG_PEEK); |
290 | socket_errno = (r < 0) ? errno : 0; | 304 | socket_errno = (r < 0) ? errno : 0; |
291 | # endif | 305 | # endif |
292 | if (r == 0) | 306 | if (r == 0) |
293 | happened |= POLLHUP; | 307 | happened |= POLLHUP; |
294 | 308 | ||
295 | /* If the event happened on an unconnected server socket, | 309 | /* If the event happened on an unconnected server socket, |
296 | that's fine. */ | 310 | that's fine. */ |
297 | else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN)) | 311 | else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN)) |
298 | happened |= (POLLIN | POLLRDNORM) & sought; | 312 | happened |= (POLLIN | POLLRDNORM) & sought; |
299 | 313 | ||
300 | /* Distinguish hung-up sockets from other errors. */ | 314 | /* Distinguish hung-up sockets from other errors. */ |
301 | else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET | 315 | else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET |
302 | || socket_errno == ECONNABORTED || socket_errno == ENETRESET) | 316 | || socket_errno == ECONNABORTED || socket_errno == ENETRESET) |
303 | happened |= POLLHUP; | 317 | happened |= POLLHUP; |
318 | |||
319 | /* some systems can't use recv() on non-socket, including HP NonStop */ | ||
320 | else if (socket_errno == ENOTSOCK) | ||
321 | happened |= (POLLIN | POLLRDNORM) & sought; | ||
304 | 322 | ||
305 | else | 323 | else |
306 | happened |= POLLERR; | 324 | happened |= POLLERR; |
307 | } | 325 | } |
308 | 326 | ||
309 | if (FD_ISSET (fd, wfds)) | 327 | if (FD_ISSET (fd, wfds)) |
@@ -319,37 +337,26 @@ compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds) | |||
319 | int | 337 | int |
320 | poll (struct pollfd *pfd, nfds_t nfd, int timeout) | 338 | poll (struct pollfd *pfd, nfds_t nfd, int timeout) |
321 | { | 339 | { |
322 | #ifndef WIN32_NATIVE | 340 | #ifndef WINDOWS_NATIVE |
323 | fd_set rfds, wfds, efds; | 341 | fd_set rfds, wfds, efds; |
324 | struct timeval tv; | 342 | struct timeval tv; |
325 | struct timeval *ptv; | 343 | struct timeval *ptv; |
326 | int maxfd, rc; | 344 | int maxfd, rc; |
327 | nfds_t i; | 345 | nfds_t i; |
328 | 346 | ||
329 | # ifdef _SC_OPEN_MAX | 347 | if (nfd > INT_MAX) |
330 | static int sc_open_max = -1; | ||
331 | |||
332 | if (nfd < 0 | ||
333 | || (nfd > sc_open_max | ||
334 | && (sc_open_max != -1 | ||
335 | || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX))))) | ||
336 | { | 348 | { |
337 | errno = EINVAL; | 349 | errno = EINVAL; |
338 | return -1; | 350 | return -1; |
339 | } | 351 | } |
340 | # else /* !_SC_OPEN_MAX */ | 352 | /* Don't check directly for NFD greater than OPEN_MAX. Any practical use |
341 | # ifdef OPEN_MAX | 353 | of a too-large NFD is caught by one of the other checks below, and |
342 | if (nfd < 0 || nfd > OPEN_MAX) | 354 | checking directly for getdtablesize is too much of a portability |
343 | { | 355 | and/or performance and/or correctness hassle. */ |
344 | errno = EINVAL; | ||
345 | return -1; | ||
346 | } | ||
347 | # endif /* OPEN_MAX -- else, no check is needed */ | ||
348 | # endif /* !_SC_OPEN_MAX */ | ||
349 | 356 | ||
350 | /* EFAULT is not necessary to implement, but let's do it in the | 357 | /* EFAULT is not necessary to implement, but let's do it in the |
351 | simplest case. */ | 358 | simplest case. */ |
352 | if (!pfd) | 359 | if (!pfd && nfd) |
353 | { | 360 | { |
354 | errno = EFAULT; | 361 | errno = EFAULT; |
355 | return -1; | 362 | return -1; |
@@ -385,30 +392,26 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | |||
385 | for (i = 0; i < nfd; i++) | 392 | for (i = 0; i < nfd; i++) |
386 | { | 393 | { |
387 | if (pfd[i].fd < 0) | 394 | if (pfd[i].fd < 0) |
388 | continue; | 395 | continue; |
389 | 396 | if (maxfd < pfd[i].fd) | |
397 | { | ||
398 | maxfd = pfd[i].fd; | ||
399 | if (FD_SETSIZE <= maxfd) | ||
400 | { | ||
401 | errno = EINVAL; | ||
402 | return -1; | ||
403 | } | ||
404 | } | ||
390 | if (pfd[i].events & (POLLIN | POLLRDNORM)) | 405 | if (pfd[i].events & (POLLIN | POLLRDNORM)) |
391 | FD_SET (pfd[i].fd, &rfds); | 406 | FD_SET (pfd[i].fd, &rfds); |
392 | 407 | ||
393 | /* see select(2): "the only exceptional condition detectable | 408 | /* see select(2): "the only exceptional condition detectable |
394 | is out-of-band data received on a socket", hence we push | 409 | is out-of-band data received on a socket", hence we push |
395 | POLLWRBAND events onto wfds instead of efds. */ | 410 | POLLWRBAND events onto wfds instead of efds. */ |
396 | if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) | 411 | if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) |
397 | FD_SET (pfd[i].fd, &wfds); | 412 | FD_SET (pfd[i].fd, &wfds); |
398 | if (pfd[i].events & (POLLPRI | POLLRDBAND)) | 413 | if (pfd[i].events & (POLLPRI | POLLRDBAND)) |
399 | FD_SET (pfd[i].fd, &efds); | 414 | FD_SET (pfd[i].fd, &efds); |
400 | if (pfd[i].fd >= maxfd | ||
401 | && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI | ||
402 | | POLLRDNORM | POLLRDBAND | ||
403 | | POLLWRNORM | POLLWRBAND))) | ||
404 | { | ||
405 | maxfd = pfd[i].fd; | ||
406 | if (maxfd > FD_SETSIZE) | ||
407 | { | ||
408 | errno = EOVERFLOW; | ||
409 | return -1; | ||
410 | } | ||
411 | } | ||
412 | } | 415 | } |
413 | 416 | ||
414 | /* examine fd sets */ | 417 | /* examine fd sets */ |
@@ -419,18 +422,13 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | |||
419 | /* establish results */ | 422 | /* establish results */ |
420 | rc = 0; | 423 | rc = 0; |
421 | for (i = 0; i < nfd; i++) | 424 | for (i = 0; i < nfd; i++) |
422 | if (pfd[i].fd < 0) | 425 | { |
423 | pfd[i].revents = 0; | 426 | pfd[i].revents = (pfd[i].fd < 0 |
424 | else | 427 | ? 0 |
425 | { | 428 | : compute_revents (pfd[i].fd, pfd[i].events, |
426 | int happened = compute_revents (pfd[i].fd, pfd[i].events, | 429 | &rfds, &wfds, &efds)); |
427 | &rfds, &wfds, &efds); | 430 | rc += pfd[i].revents != 0; |
428 | if (happened) | 431 | } |
429 | { | ||
430 | pfd[i].revents = happened; | ||
431 | rc++; | ||
432 | } | ||
433 | } | ||
434 | 432 | ||
435 | return rc; | 433 | return rc; |
436 | #else | 434 | #else |
@@ -445,7 +443,7 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) | |||
445 | int rc = 0; | 443 | int rc = 0; |
446 | nfds_t i; | 444 | nfds_t i; |
447 | 445 | ||
448 | if (nfd < 0 || timeout < -1) | 446 | if (nfd > INT_MAX || timeout < -1) |
449 | { | 447 | { |
450 | errno = EINVAL; | 448 | errno = EINVAL; |
451 | return -1; | 449 | return -1; |
@@ -467,55 +465,55 @@ restart: | |||
467 | int sought = pfd[i].events; | 465 | int sought = pfd[i].events; |
468 | pfd[i].revents = 0; | 466 | pfd[i].revents = 0; |
469 | if (pfd[i].fd < 0) | 467 | if (pfd[i].fd < 0) |
470 | continue; | 468 | continue; |
471 | if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND | 469 | if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND |
472 | | POLLPRI | POLLRDBAND))) | 470 | | POLLPRI | POLLRDBAND))) |
473 | continue; | 471 | continue; |
474 | 472 | ||
475 | h = (HANDLE) _get_osfhandle (pfd[i].fd); | 473 | h = (HANDLE) _get_osfhandle (pfd[i].fd); |
476 | assert (h != NULL); | 474 | assert (h != NULL); |
477 | if (IsSocketHandle (h)) | 475 | if (IsSocketHandle (h)) |
478 | { | 476 | { |
479 | int requested = FD_CLOSE; | 477 | int requested = FD_CLOSE; |
480 | 478 | ||
481 | /* see above; socket handles are mapped onto select. */ | 479 | /* see above; socket handles are mapped onto select. */ |
482 | if (sought & (POLLIN | POLLRDNORM)) | 480 | if (sought & (POLLIN | POLLRDNORM)) |
483 | { | 481 | { |
484 | requested |= FD_READ | FD_ACCEPT; | 482 | requested |= FD_READ | FD_ACCEPT; |
485 | FD_SET ((SOCKET) h, &rfds); | 483 | FD_SET ((SOCKET) h, &rfds); |
486 | } | 484 | } |
487 | if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND)) | 485 | if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND)) |
488 | { | 486 | { |
489 | requested |= FD_WRITE | FD_CONNECT; | 487 | requested |= FD_WRITE | FD_CONNECT; |
490 | FD_SET ((SOCKET) h, &wfds); | 488 | FD_SET ((SOCKET) h, &wfds); |
491 | } | 489 | } |
492 | if (sought & (POLLPRI | POLLRDBAND)) | 490 | if (sought & (POLLPRI | POLLRDBAND)) |
493 | { | 491 | { |
494 | requested |= FD_OOB; | 492 | requested |= FD_OOB; |
495 | FD_SET ((SOCKET) h, &xfds); | 493 | FD_SET ((SOCKET) h, &xfds); |
496 | } | 494 | } |
497 | 495 | ||
498 | if (requested) | 496 | if (requested) |
499 | WSAEventSelect ((SOCKET) h, hEvent, requested); | 497 | WSAEventSelect ((SOCKET) h, hEvent, requested); |
500 | } | 498 | } |
501 | else | 499 | else |
502 | { | 500 | { |
503 | /* Poll now. If we get an event, do not poll again. Also, | 501 | /* Poll now. If we get an event, do not poll again. Also, |
504 | screen buffer handles are waitable, and they'll block until | 502 | screen buffer handles are waitable, and they'll block until |
505 | a character is available. win32_compute_revents eliminates | 503 | a character is available. windows_compute_revents eliminates |
506 | bits for the "wrong" direction. */ | 504 | bits for the "wrong" direction. */ |
507 | pfd[i].revents = win32_compute_revents (h, &sought); | 505 | pfd[i].revents = windows_compute_revents (h, &sought); |
508 | if (sought) | 506 | if (sought) |
509 | handle_array[nhandles++] = h; | 507 | handle_array[nhandles++] = h; |
510 | if (pfd[i].revents) | 508 | if (pfd[i].revents) |
511 | timeout = 0; | 509 | timeout = 0; |
512 | } | 510 | } |
513 | } | 511 | } |
514 | 512 | ||
515 | if (select (0, &rfds, &wfds, &xfds, &tv0) > 0) | 513 | if (select (0, &rfds, &wfds, &xfds, &tv0) > 0) |
516 | { | 514 | { |
517 | /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but | 515 | /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but |
518 | no need to call select again. */ | 516 | no need to call select again. */ |
519 | poll_again = FALSE; | 517 | poll_again = FALSE; |
520 | wait_timeout = 0; | 518 | wait_timeout = 0; |
521 | } | 519 | } |
@@ -523,28 +521,28 @@ restart: | |||
523 | { | 521 | { |
524 | poll_again = TRUE; | 522 | poll_again = TRUE; |
525 | if (timeout == INFTIM) | 523 | if (timeout == INFTIM) |
526 | wait_timeout = INFINITE; | 524 | wait_timeout = INFINITE; |
527 | else | 525 | else |
528 | wait_timeout = timeout; | 526 | wait_timeout = timeout; |
529 | } | 527 | } |
530 | 528 | ||
531 | for (;;) | 529 | for (;;) |
532 | { | 530 | { |
533 | ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, | 531 | ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE, |
534 | wait_timeout, QS_ALLINPUT); | 532 | wait_timeout, QS_ALLINPUT); |
535 | 533 | ||
536 | if (ret == WAIT_OBJECT_0 + nhandles) | 534 | if (ret == WAIT_OBJECT_0 + nhandles) |
537 | { | 535 | { |
538 | /* new input of some other kind */ | 536 | /* new input of some other kind */ |
539 | BOOL bRet; | 537 | BOOL bRet; |
540 | while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) | 538 | while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0) |
541 | { | 539 | { |
542 | TranslateMessage (&msg); | 540 | TranslateMessage (&msg); |
543 | DispatchMessage (&msg); | 541 | DispatchMessage (&msg); |
544 | } | 542 | } |
545 | } | 543 | } |
546 | else | 544 | else |
547 | break; | 545 | break; |
548 | } | 546 | } |
549 | 547 | ||
550 | if (poll_again) | 548 | if (poll_again) |
@@ -558,46 +556,46 @@ restart: | |||
558 | int happened; | 556 | int happened; |
559 | 557 | ||
560 | if (pfd[i].fd < 0) | 558 | if (pfd[i].fd < 0) |
561 | continue; | 559 | continue; |
562 | if (!(pfd[i].events & (POLLIN | POLLRDNORM | | 560 | if (!(pfd[i].events & (POLLIN | POLLRDNORM | |
563 | POLLOUT | POLLWRNORM | POLLWRBAND))) | 561 | POLLOUT | POLLWRNORM | POLLWRBAND))) |
564 | continue; | 562 | continue; |
565 | 563 | ||
566 | h = (HANDLE) _get_osfhandle (pfd[i].fd); | 564 | h = (HANDLE) _get_osfhandle (pfd[i].fd); |
567 | if (h != handle_array[nhandles]) | 565 | if (h != handle_array[nhandles]) |
568 | { | 566 | { |
569 | /* It's a socket. */ | 567 | /* It's a socket. */ |
570 | WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); | 568 | WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev); |
571 | WSAEventSelect ((SOCKET) h, 0, 0); | 569 | WSAEventSelect ((SOCKET) h, 0, 0); |
572 | 570 | ||
573 | /* If we're lucky, WSAEnumNetworkEvents already provided a way | 571 | /* If we're lucky, WSAEnumNetworkEvents already provided a way |
574 | to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */ | 572 | to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */ |
575 | if (FD_ISSET ((SOCKET) h, &rfds) | 573 | if (FD_ISSET ((SOCKET) h, &rfds) |
576 | && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT))) | 574 | && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT))) |
577 | ev.lNetworkEvents |= FD_READ | FD_ACCEPT; | 575 | ev.lNetworkEvents |= FD_READ | FD_ACCEPT; |
578 | if (FD_ISSET ((SOCKET) h, &wfds)) | 576 | if (FD_ISSET ((SOCKET) h, &wfds)) |
579 | ev.lNetworkEvents |= FD_WRITE | FD_CONNECT; | 577 | ev.lNetworkEvents |= FD_WRITE | FD_CONNECT; |
580 | if (FD_ISSET ((SOCKET) h, &xfds)) | 578 | if (FD_ISSET ((SOCKET) h, &xfds)) |
581 | ev.lNetworkEvents |= FD_OOB; | 579 | ev.lNetworkEvents |= FD_OOB; |
582 | 580 | ||
583 | happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events, | 581 | happened = windows_compute_revents_socket ((SOCKET) h, pfd[i].events, |
584 | ev.lNetworkEvents); | 582 | ev.lNetworkEvents); |
585 | } | 583 | } |
586 | else | 584 | else |
587 | { | 585 | { |
588 | /* Not a socket. */ | 586 | /* Not a socket. */ |
589 | int sought = pfd[i].events; | 587 | int sought = pfd[i].events; |
590 | happened = win32_compute_revents (h, &sought); | 588 | happened = windows_compute_revents (h, &sought); |
591 | nhandles++; | 589 | nhandles++; |
592 | } | 590 | } |
593 | 591 | ||
594 | if ((pfd[i].revents |= happened) != 0) | 592 | if ((pfd[i].revents |= happened) != 0) |
595 | rc++; | 593 | rc++; |
596 | } | 594 | } |
597 | 595 | ||
598 | if (!rc && timeout == INFTIM) | 596 | if (!rc && timeout == INFTIM) |
599 | { | 597 | { |
600 | SwitchToThread(); | 598 | SleepEx (1, TRUE); |
601 | goto restart; | 599 | goto restart; |
602 | } | 600 | } |
603 | 601 | ||