~ubuntu-branches/ubuntu/lucid/curl/lucid-201101212007

« back to all changes in this revision

Viewing changes to lib/select.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-05-16 15:16:54 UTC
  • mto: (3.1.1 lenny) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: james.westby@ubuntu.com-20070516151654-x9nkigtr2j0i8d0v
Tags: upstream-7.16.2
ImportĀ upstreamĀ versionĀ 7.16.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: select.c,v 1.17 2006-05-05 10:24:27 bagder Exp $
 
21
 * $Id: select.c,v 1.40 2007-04-04 06:06:36 yangtse Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
#include "setup.h"
25
25
 
26
 
#include <errno.h>
27
 
 
28
 
#ifdef HAVE_SYS_TYPES_H
29
 
#include <sys/types.h>
30
 
#endif
31
26
#ifdef HAVE_SYS_SELECT_H
32
27
#include <sys/select.h>
33
28
#endif
35
30
#include <sys/time.h>
36
31
#endif
37
32
 
38
 
#ifndef HAVE_SELECT
39
 
#error "We can't compile without select() support!"
 
33
#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
 
34
#error "We can't compile without select() or poll() support."
40
35
#endif
41
36
 
42
37
#ifdef __BEOS__
44
39
#include <socket.h>
45
40
#endif
46
41
 
 
42
#ifdef MSDOS
 
43
#include <dos.h>  /* delay() */
 
44
#endif
 
45
 
47
46
#include <curl/curl.h>
48
47
 
49
48
#include "urldata.h"
50
49
#include "connect.h"
51
50
#include "select.h"
52
51
 
53
 
#if defined(WIN32) || defined(TPF)
54
 
#define VERIFY_SOCK(x)  /* sockets are not in range [0..FD_SETSIZE] */
 
52
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1] */
 
53
 
 
54
#if defined(USE_WINSOCK) || defined(TPF)
 
55
#define VERIFY_SOCK(x) do { } while (0)
 
56
#define VERIFY_NFDS(x) do { } while (0)
55
57
#else
56
58
#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
57
59
#define VERIFY_SOCK(x) do { \
58
60
  if(!VALID_SOCK(x)) { \
59
 
    errno = EINVAL; \
60
 
    return -1; \
61
 
  } \
62
 
} while(0)
63
 
#endif
 
61
    SET_SOCKERRNO(EINVAL); \
 
62
    return -1; \
 
63
  } \
 
64
} while(0)
 
65
#define VALID_NFDS(n) (((n) >= 0) && ((n) <= FD_SETSIZE))
 
66
#define VERIFY_NFDS(x) do { \
 
67
  if(!VALID_NFDS(x)) { \
 
68
    SET_SOCKERRNO(EINVAL); \
 
69
    return -1; \
 
70
  } \
 
71
} while(0)
 
72
#endif
 
73
 
 
74
/* Convenience local macros */
 
75
 
 
76
#define elapsed_ms  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
 
77
 
 
78
#ifdef CURL_ACKNOWLEDGE_EINTR
 
79
#define error_not_EINTR  (error != EINTR)
 
80
#else
 
81
#define error_not_EINTR  (1)
 
82
#endif
 
83
 
 
84
#define SMALL_POLLNFDS  0X20
 
85
 
 
86
/*
 
87
 * Internal function used for waiting a specific amount of ms
 
88
 * in Curl_socket_ready() and Curl_poll() when no file descriptor
 
89
 * is provided to wait on, just being used to delay execution.
 
90
 * WinSock select() and poll() timeout mechanisms need a valid
 
91
 * socket descriptor in a not null file descriptor set to work.
 
92
 * Waiting indefinitely with this function is not allowed, a
 
93
 * zero or negative timeout value will return immediately.
 
94
 * Timeout resolution, accuracy, as well as maximum supported
 
95
 * value is system dependant, neither factor is a citical issue
 
96
 * for the intended use of this function in the library.
 
97
 * On non-DOS and non-Winsock platforms, when compiled with
 
98
 * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored
 
99
 * and function might exit early without awaiting full timeout,
 
100
 * otherwise EINTR will be ignored and full timeout will elapse.
 
101
 *
 
102
 * Return values:
 
103
 *   -1 = system call error, invalid timeout value, or interrupted
 
104
 *    0 = specified timeout has elapsed
 
105
 */
 
106
static int wait_ms(int timeout_ms)
 
107
{
 
108
#if !defined(MSDOS) && !defined(USE_WINSOCK)
 
109
#ifndef HAVE_POLL_FINE
 
110
  struct timeval pending_tv;
 
111
#endif
 
112
  struct timeval initial_tv;
 
113
  int pending_ms;
 
114
  int error;
 
115
#endif
 
116
  int r = 0;
 
117
 
 
118
  if (!timeout_ms)
 
119
    return 0;
 
120
  if (timeout_ms < 0) {
 
121
    SET_SOCKERRNO(EINVAL);
 
122
    return -1;
 
123
  }
 
124
#if defined(MSDOS)
 
125
  delay(timeout_ms);
 
126
#elif defined(USE_WINSOCK)
 
127
  Sleep(timeout_ms);
 
128
#else
 
129
  pending_ms = timeout_ms;
 
130
  initial_tv = curlx_tvnow();
 
131
  do {
 
132
#if defined(HAVE_POLL_FINE)
 
133
    r = poll(NULL, 0, pending_ms);
 
134
#else
 
135
    pending_tv.tv_sec = pending_ms / 1000;
 
136
    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 
137
    r = select(0, NULL, NULL, NULL, &pending_tv);
 
138
#endif /* HAVE_POLL_FINE */
 
139
  } while ((r == -1) && (error = SOCKERRNO) &&
 
140
           (error != EINVAL) && error_not_EINTR &&
 
141
           ((pending_ms = timeout_ms - elapsed_ms) > 0));
 
142
#endif /* USE_WINSOCK */
 
143
  if (r)
 
144
    r = -1;
 
145
  return r;
 
146
}
64
147
 
65
148
/*
66
149
 * This is an internal function used for waiting for read or write
67
 
 * events on single file descriptors.  It attempts to replace select()
68
 
 * in order to avoid limits with FD_SETSIZE.
 
150
 * events on a pair of file descriptors.  It uses poll() when a fine
 
151
 * poll() is available, in order to avoid limits with FD_SETSIZE,
 
152
 * otherwise select() is used.  An error is returned if select() is
 
153
 * being used and a file descriptor is too large for FD_SETSIZE.
 
154
 * A negative timeout value makes this function wait indefinitely,
 
155
 * unles no valid file descriptor is given, when this happens the
 
156
 * negative timeout is ignored and the function times out immediately.
 
157
 * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
 
158
 * is honored and function might exit early without awaiting timeout,
 
159
 * otherwise EINTR will be ignored.
69
160
 *
70
161
 * Return values:
71
 
 *   -1 = system call error
 
162
 *   -1 = system call error or fd >= FD_SETSIZE
72
163
 *    0 = timeout
73
164
 *    CSELECT_IN | CSELECT_OUT | CSELECT_ERR
74
165
 */
75
 
int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
 
166
int Curl_socket_ready(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
76
167
{
77
168
#ifdef HAVE_POLL_FINE
78
169
  struct pollfd pfd[2];
79
170
  int num;
 
171
#else
 
172
  struct timeval pending_tv;
 
173
  struct timeval *ptimeout;
 
174
  fd_set fds_read;
 
175
  fd_set fds_write;
 
176
  fd_set fds_err;
 
177
  curl_socket_t maxfd;
 
178
#endif
 
179
  struct timeval initial_tv;
 
180
  int pending_ms;
 
181
  int error;
80
182
  int r;
81
183
  int ret;
82
184
 
 
185
  if((readfd == CURL_SOCKET_BAD) && (writefd == CURL_SOCKET_BAD)) {
 
186
    r = wait_ms(timeout_ms);
 
187
    return r;
 
188
  }
 
189
 
 
190
  pending_ms = timeout_ms;
 
191
  initial_tv = curlx_tvnow();
 
192
 
 
193
#ifdef HAVE_POLL_FINE
 
194
 
83
195
  num = 0;
84
196
  if (readfd != CURL_SOCKET_BAD) {
85
197
    pfd[num].fd = readfd;
86
 
    pfd[num].events = POLLIN;
 
198
    pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
 
199
    pfd[num].revents = 0;
87
200
    num++;
88
201
  }
89
202
  if (writefd != CURL_SOCKET_BAD) {
90
203
    pfd[num].fd = writefd;
91
 
    pfd[num].events = POLLOUT;
 
204
    pfd[num].events = POLLWRNORM|POLLOUT;
 
205
    pfd[num].revents = 0;
92
206
    num++;
93
207
  }
94
208
 
95
209
  do {
96
 
    r = poll(pfd, num, timeout_ms);
97
 
  } while((r == -1) && (errno == EINTR));
 
210
    if (timeout_ms < 0)
 
211
      pending_ms = -1;
 
212
    r = poll(pfd, num, pending_ms);
 
213
  } while ((r == -1) && (error = SOCKERRNO) &&
 
214
           (error != EINVAL) && error_not_EINTR &&
 
215
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
98
216
 
99
217
  if (r < 0)
100
218
    return -1;
104
222
  ret = 0;
105
223
  num = 0;
106
224
  if (readfd != CURL_SOCKET_BAD) {
107
 
    if (pfd[num].revents & (POLLIN|POLLHUP))
 
225
    if (pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
108
226
      ret |= CSELECT_IN;
109
 
    if (pfd[num].revents & POLLERR)
 
227
    if (pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
110
228
      ret |= CSELECT_ERR;
111
229
    num++;
112
230
  }
113
231
  if (writefd != CURL_SOCKET_BAD) {
114
 
    if (pfd[num].revents & POLLOUT)
 
232
    if (pfd[num].revents & (POLLWRNORM|POLLOUT))
115
233
      ret |= CSELECT_OUT;
116
 
    if (pfd[num].revents & POLLERR)
 
234
    if (pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
117
235
      ret |= CSELECT_ERR;
118
236
  }
119
237
 
120
238
  return ret;
121
 
#else
122
 
  struct timeval timeout;
123
 
  fd_set fds_read;
124
 
  fd_set fds_write;
125
 
  fd_set fds_err;
126
 
  curl_socket_t maxfd;
127
 
  int r;
128
 
  int ret;
129
239
 
130
 
  timeout.tv_sec = timeout_ms / 1000;
131
 
  timeout.tv_usec = (timeout_ms % 1000) * 1000;
 
240
#else  /* HAVE_POLL_FINE */
132
241
 
133
242
  FD_ZERO(&fds_err);
134
243
  maxfd = (curl_socket_t)-1;
150
259
      maxfd = writefd;
151
260
  }
152
261
 
 
262
  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
263
 
153
264
  do {
154
 
    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, &timeout);
155
 
  } while((r == -1) && (Curl_sockerrno() == EINTR));
 
265
    if (ptimeout) {
 
266
      pending_tv.tv_sec = pending_ms / 1000;
 
267
      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 
268
    }
 
269
    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 
270
  } while ((r == -1) && (error = SOCKERRNO) &&
 
271
           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
 
272
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
156
273
 
157
274
  if (r < 0)
158
275
    return -1;
174
291
  }
175
292
 
176
293
  return ret;
177
 
#endif
 
294
 
 
295
#endif  /* HAVE_POLL_FINE */
 
296
 
178
297
}
179
298
 
180
299
/*
181
300
 * This is a wrapper around poll().  If poll() does not exist, then
182
301
 * select() is used instead.  An error is returned if select() is
183
 
 * being used and a file descriptor too large for FD_SETSIZE.
 
302
 * being used and a file descriptor is too large for FD_SETSIZE.
 
303
 * A negative timeout value makes this function wait indefinitely,
 
304
 * unles no valid file descriptor is given, when this happens the
 
305
 * negative timeout is ignored and the function times out immediately.
 
306
 * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition
 
307
 * is honored and function might exit early without awaiting timeout,
 
308
 * otherwise EINTR will be ignored.
184
309
 *
185
310
 * Return values:
186
311
 *   -1 = system call error or fd >= FD_SETSIZE
187
312
 *    0 = timeout
188
 
 *    1 = number of structures with non zero revent fields
 
313
 *    N = number of structures with non zero revent fields
189
314
 */
190
315
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
191
316
{
192
 
  int r;
193
 
#ifdef HAVE_POLL_FINE
194
 
  do {
195
 
    r = poll(ufds, nfds, timeout_ms);
196
 
  } while((r == -1) && (errno == EINTR));
197
 
#else
198
 
  struct timeval timeout;
 
317
#ifndef HAVE_POLL_FINE
 
318
  struct timeval pending_tv;
199
319
  struct timeval *ptimeout;
200
320
  fd_set fds_read;
201
321
  fd_set fds_write;
202
322
  fd_set fds_err;
203
323
  curl_socket_t maxfd;
 
324
#endif
 
325
  struct timeval initial_tv;
 
326
  bool fds_none = TRUE;
204
327
  unsigned int i;
 
328
  int pending_ms;
 
329
  int error;
 
330
  int r;
 
331
 
 
332
  if (ufds) {
 
333
    for (i = 0; i < nfds; i++) {
 
334
      if (ufds[i].fd != CURL_SOCKET_BAD) {
 
335
        fds_none = FALSE;
 
336
        break;
 
337
      }
 
338
    }
 
339
  }
 
340
  if (fds_none) {
 
341
    r = wait_ms(timeout_ms);
 
342
    return r;
 
343
  }
 
344
 
 
345
  pending_ms = timeout_ms;
 
346
  initial_tv = curlx_tvnow();
 
347
 
 
348
#ifdef HAVE_POLL_FINE
 
349
 
 
350
  do {
 
351
    if (timeout_ms < 0)
 
352
      pending_ms = -1;
 
353
    r = poll(ufds, nfds, pending_ms);
 
354
  } while ((r == -1) && (error = SOCKERRNO) &&
 
355
           (error != EINVAL) && error_not_EINTR &&
 
356
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
 
357
 
 
358
#else  /* HAVE_POLL_FINE */
205
359
 
206
360
  FD_ZERO(&fds_read);
207
361
  FD_ZERO(&fds_write);
209
363
  maxfd = (curl_socket_t)-1;
210
364
 
211
365
  for (i = 0; i < nfds; i++) {
 
366
    ufds[i].revents = 0;
212
367
    if (ufds[i].fd == CURL_SOCKET_BAD)
213
368
      continue;
214
 
#ifndef WIN32  /* This is harmless and wrong on Win32 */
215
 
    if (ufds[i].fd >= FD_SETSIZE) {
216
 
      errno = EINVAL;
217
 
      return -1;
 
369
    VERIFY_SOCK(ufds[i].fd);
 
370
    if (ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
 
371
                          POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
 
372
      if (ufds[i].fd > maxfd)
 
373
        maxfd = ufds[i].fd;
 
374
      if (ufds[i].events & (POLLRDNORM|POLLIN))
 
375
        FD_SET(ufds[i].fd, &fds_read);
 
376
      if (ufds[i].events & (POLLWRNORM|POLLOUT))
 
377
        FD_SET(ufds[i].fd, &fds_write);
 
378
      if (ufds[i].events & (POLLRDBAND|POLLPRI))
 
379
        FD_SET(ufds[i].fd, &fds_err);
218
380
    }
219
 
#endif
220
 
    if (ufds[i].fd > maxfd)
221
 
      maxfd = ufds[i].fd;
222
 
    if (ufds[i].events & POLLIN)
223
 
      FD_SET(ufds[i].fd, &fds_read);
224
 
    if (ufds[i].events & POLLOUT)
225
 
      FD_SET(ufds[i].fd, &fds_write);
226
 
    if (ufds[i].events & POLLERR)
227
 
      FD_SET(ufds[i].fd, &fds_err);
228
381
  }
229
382
 
230
 
  if (timeout_ms < 0) {
231
 
    ptimeout = NULL;      /* wait forever */
232
 
  } else {
233
 
    timeout.tv_sec = timeout_ms / 1000;
234
 
    timeout.tv_usec = (timeout_ms % 1000) * 1000;
235
 
    ptimeout = &timeout;
236
 
  }
 
383
  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
237
384
 
238
385
  do {
 
386
    if (ptimeout) {
 
387
      pending_tv.tv_sec = pending_ms / 1000;
 
388
      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 
389
    }
239
390
    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
240
 
  } while((r == -1) && (Curl_sockerrno() == EINTR));
 
391
  } while ((r == -1) && (error = SOCKERRNO) &&
 
392
           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
 
393
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
241
394
 
242
395
  if (r < 0)
243
396
    return -1;
254
407
    if (FD_ISSET(ufds[i].fd, &fds_write))
255
408
      ufds[i].revents |= POLLOUT;
256
409
    if (FD_ISSET(ufds[i].fd, &fds_err))
257
 
      ufds[i].revents |= POLLERR;
 
410
      ufds[i].revents |= POLLPRI;
258
411
    if (ufds[i].revents != 0)
259
412
      r++;
260
413
  }
 
414
 
 
415
#endif  /* HAVE_POLL_FINE */
 
416
 
 
417
  return r;
 
418
}
 
419
 
 
420
/*
 
421
 * This is a wrapper around select().  It uses poll() when a fine
 
422
 * poll() is available, in order to avoid limits with FD_SETSIZE,
 
423
 * otherwise select() is used.  An error is returned if select() is
 
424
 * being used and a the number of file descriptors is larger than
 
425
 * FD_SETSIZE.  A NULL timeout pointer makes this function wait
 
426
 * indefinitely, unles no valid file descriptor is given, when this
 
427
 * happens the NULL timeout is ignored and the function times out
 
428
 * immediately.  When compiled with CURL_ACKNOWLEDGE_EINTR defined,
 
429
 * EINTR condition is honored and function might exit early without
 
430
 * awaiting timeout, otherwise EINTR will be ignored.
 
431
 *
 
432
 * Return values:
 
433
 *   -1 = system call error or nfds > FD_SETSIZE
 
434
 *    0 = timeout
 
435
 *    N = number of file descriptors kept in file descriptor sets.
 
436
 */
 
437
int Curl_select(int nfds,
 
438
                fd_set *fds_read, fd_set *fds_write, fd_set *fds_excep,
 
439
                struct timeval *timeout)
 
440
{
 
441
  struct timeval initial_tv;
 
442
  int timeout_ms;
 
443
  int pending_ms;
 
444
  int error;
 
445
  int r;
 
446
#ifdef HAVE_POLL_FINE
 
447
  struct pollfd small_fds[SMALL_POLLNFDS];
 
448
  struct pollfd *poll_fds;
 
449
  int ix;
 
450
  int fd;
 
451
  int poll_nfds = 0;
 
452
#else
 
453
  struct timeval pending_tv;
 
454
  struct timeval *ptimeout;
261
455
#endif
262
 
  return r;
 
456
  int ret = 0;
 
457
 
 
458
  if ((nfds < 0) ||
 
459
     ((nfds > 0) && (!fds_read && !fds_write && !fds_excep))) {
 
460
    SET_SOCKERRNO(EINVAL);
 
461
    return -1;
 
462
  }
 
463
 
 
464
  if (timeout) {
 
465
    if ((timeout->tv_sec < 0) ||
 
466
        (timeout->tv_usec < 0) ||
 
467
        (timeout->tv_usec >= 1000000)) {
 
468
      SET_SOCKERRNO(EINVAL);
 
469
      return -1;
 
470
    }
 
471
    timeout_ms = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
 
472
  }
 
473
  else {
 
474
    timeout_ms = -1;
 
475
  }
 
476
 
 
477
  if ((!nfds) || (!fds_read && !fds_write && !fds_excep)) {
 
478
    r = wait_ms(timeout_ms);
 
479
    return r;
 
480
  }
 
481
 
 
482
  pending_ms = timeout_ms;
 
483
  initial_tv = curlx_tvnow();
 
484
 
 
485
#ifdef HAVE_POLL_FINE
 
486
 
 
487
  if (fds_read || fds_write || fds_excep) {
 
488
    fd = nfds;
 
489
    while (fd--) {
 
490
      if ((fds_read && (0 != FD_ISSET(fd, fds_read))) ||
 
491
          (fds_write && (0 != FD_ISSET(fd, fds_write))) ||
 
492
          (fds_excep && (0 != FD_ISSET(fd, fds_excep))))
 
493
        poll_nfds++;
 
494
    }
 
495
  }
 
496
 
 
497
  if (!poll_nfds)
 
498
    poll_fds = NULL;
 
499
  else if (poll_nfds <= SMALL_POLLNFDS)
 
500
    poll_fds = small_fds;
 
501
  else {
 
502
    poll_fds = calloc((size_t)poll_nfds, sizeof(struct pollfd));
 
503
    if (!poll_fds) {
 
504
      SET_SOCKERRNO(ENOBUFS);
 
505
      return -1;
 
506
    }
 
507
  }
 
508
 
 
509
  if (poll_fds) {
 
510
    ix = 0;
 
511
    fd = nfds;
 
512
    while (fd--) {
 
513
      poll_fds[ix].events = 0;
 
514
      if (fds_read && (0 != FD_ISSET(fd, fds_read)))
 
515
        poll_fds[ix].events |= (POLLRDNORM|POLLIN);
 
516
      if (fds_write && (0 != FD_ISSET(fd, fds_write)))
 
517
        poll_fds[ix].events |= (POLLWRNORM|POLLOUT);
 
518
      if (fds_excep && (0 != FD_ISSET(fd, fds_excep)))
 
519
        poll_fds[ix].events |= (POLLRDBAND|POLLPRI);
 
520
      if (poll_fds[ix].events) {
 
521
        poll_fds[ix].fd = fd;
 
522
        poll_fds[ix].revents = 0;
 
523
        ix++;
 
524
      }
 
525
    }
 
526
  }
 
527
 
 
528
  do {
 
529
    if (timeout_ms < 0)
 
530
      pending_ms = -1;
 
531
    r = poll(poll_fds, poll_nfds, pending_ms);
 
532
  } while ((r == -1) && (error = SOCKERRNO) &&
 
533
           (error != EINVAL) && error_not_EINTR &&
 
534
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
 
535
 
 
536
  if (r < 0)
 
537
    ret = -1;
 
538
 
 
539
  if (r > 0) {
 
540
    ix = poll_nfds;
 
541
    while (ix--) {
 
542
      if (poll_fds[ix].revents & POLLNVAL) {
 
543
        SET_SOCKERRNO(EBADF);
 
544
        ret = -1;
 
545
        break;
 
546
      }
 
547
    }
 
548
  }
 
549
 
 
550
  if (!ret) {
 
551
    ix = poll_nfds;
 
552
    while (ix--) {
 
553
      if (fds_read && (0 != FD_ISSET(poll_fds[ix].fd, fds_read))) {
 
554
        if (0 == (poll_fds[ix].revents & (POLLRDNORM|POLLERR|POLLHUP|POLLIN)))
 
555
          FD_CLR(poll_fds[ix].fd, fds_read);
 
556
        else
 
557
          ret++;
 
558
      }
 
559
      if (fds_write && (0 != FD_ISSET(poll_fds[ix].fd, fds_write))) {
 
560
        if (0 == (poll_fds[ix].revents & (POLLWRNORM|POLLERR|POLLHUP|POLLOUT)))
 
561
          FD_CLR(poll_fds[ix].fd, fds_write);
 
562
        else
 
563
          ret++;
 
564
      }
 
565
      if (fds_excep && (0 != FD_ISSET(poll_fds[ix].fd, fds_excep))) {
 
566
        if (0 == (poll_fds[ix].revents & (POLLRDBAND|POLLERR|POLLHUP|POLLPRI)))
 
567
          FD_CLR(poll_fds[ix].fd, fds_excep);
 
568
        else
 
569
          ret++;
 
570
      }
 
571
    }
 
572
  }
 
573
 
 
574
  if (poll_fds && (poll_nfds > SMALL_POLLNFDS))
 
575
    free(poll_fds);
 
576
 
 
577
#else  /* HAVE_POLL_FINE */
 
578
 
 
579
  VERIFY_NFDS(nfds);
 
580
 
 
581
  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
582
 
 
583
  do {
 
584
    if (ptimeout) {
 
585
      pending_tv.tv_sec = pending_ms / 1000;
 
586
      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 
587
    }
 
588
    r = select(nfds, fds_read, fds_write, fds_excep, ptimeout);
 
589
  } while ((r == -1) && (error = SOCKERRNO) &&
 
590
           (error != EINVAL) && (error != EBADF) && error_not_EINTR &&
 
591
           ((timeout_ms < 0) || ((pending_ms = timeout_ms - elapsed_ms) > 0)));
 
592
 
 
593
  if (r < 0)
 
594
    ret = -1;
 
595
  else
 
596
    ret = r;
 
597
 
 
598
#endif  /* HAVE_POLL_FINE */
 
599
 
 
600
  return ret;
263
601
}
264
602
 
265
603
#ifdef TPF