1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
22 * $Id: select.c,v 1.2 2007/03/15 19:22:13 andy Exp $
24 * $Id: select.c,v 1.3 2008-09-15 22:23:37 hoffman Exp $
26 ***************************************************************************/
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
38 #ifdef HAVE_SYS_TIME_H
43 #error "We can't compile without select() support!"
46 #if defined(__BEOS__) && !defined(__HAIKU__)
47 /* BeOS has FD_SET defined in socket.h */
52 #include <dos.h> /* delay() */
55 #include <curl/curl.h>
61 #if defined(USE_WINSOCK) || defined(TPF)
62 #define VERIFY_SOCK(x) /* sockets are not in range [0..FD_SETSIZE] */
64 #define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE))
65 #define VERIFY_SOCK(x) do { \
66 if(!VALID_SOCK(x)) { \
74 * This is an internal function used for waiting for read or write
75 * events on single file descriptors. It attempts to replace select()
76 * in order to avoid limits with FD_SETSIZE.
79 * -1 = system call error
81 * CSELECT_IN | CSELECT_OUT | CSELECT_ERR
83 int Curl_select(curl_socket_t readfd
, curl_socket_t writefd
, int timeout_ms
)
85 #if defined(HAVE_POLL_FINE) || defined(CURL_HAVE_WSAPOLL)
92 if (readfd
!= CURL_SOCKET_BAD
) {
94 pfd
[num
].events
= POLLIN
;
97 if (writefd
!= CURL_SOCKET_BAD
) {
98 pfd
[num
].fd
= writefd
;
99 pfd
[num
].events
= POLLOUT
;
103 #ifdef HAVE_POLL_FINE
105 r
= poll(pfd
, num
, timeout_ms
);
106 } while((r
== -1) && (errno
== EINTR
));
108 r
= WSAPoll(pfd
, num
, timeout_ms
);
118 if (readfd
!= CURL_SOCKET_BAD
) {
119 if (pfd
[num
].revents
& (POLLIN
|POLLHUP
))
121 if (pfd
[num
].revents
& POLLERR
) {
123 /* Cygwin 1.5.21 needs this hack to pass test 160 */
124 if (errno
== EINPROGRESS
)
132 if (writefd
!= CURL_SOCKET_BAD
) {
133 if (pfd
[num
].revents
& POLLOUT
)
135 if (pfd
[num
].revents
& (POLLERR
|POLLHUP
))
141 struct timeval timeout
;
149 timeout
.tv_sec
= timeout_ms
/ 1000;
150 timeout
.tv_usec
= (timeout_ms
% 1000) * 1000;
152 if((readfd
== CURL_SOCKET_BAD
) && (writefd
== CURL_SOCKET_BAD
)) {
153 /* According to POSIX we should pass in NULL pointers if we don't want to
154 wait for anything in particular but just use the timeout function.
155 Windows however returns immediately if done so. I copied the MSDOS
156 delay() use from src/main.c that already had this work-around. */
159 #elif defined(__MSDOS__)
162 select(0, NULL
, NULL
, NULL
, &timeout
);
168 maxfd
= (curl_socket_t
)-1;
171 if (readfd
!= CURL_SOCKET_BAD
) {
173 FD_SET(readfd
, &fds_read
);
174 FD_SET(readfd
, &fds_err
);
179 if (writefd
!= CURL_SOCKET_BAD
) {
180 VERIFY_SOCK(writefd
);
181 FD_SET(writefd
, &fds_write
);
182 FD_SET(writefd
, &fds_err
);
188 r
= select((int)maxfd
+ 1, &fds_read
, &fds_write
, &fds_err
, &timeout
);
189 } while((r
== -1) && (Curl_sockerrno() == EINTR
));
197 if (readfd
!= CURL_SOCKET_BAD
) {
198 if (FD_ISSET(readfd
, &fds_read
))
200 if (FD_ISSET(readfd
, &fds_err
))
203 if (writefd
!= CURL_SOCKET_BAD
) {
204 if (FD_ISSET(writefd
, &fds_write
))
206 if (FD_ISSET(writefd
, &fds_err
))
215 * This is a wrapper around poll(). If poll() does not exist, then
216 * select() is used instead. An error is returned if select() is
217 * being used and a file descriptor too large for FD_SETSIZE.
220 * -1 = system call error or fd >= FD_SETSIZE
222 * 1 = number of structures with non zero revent fields
224 int Curl_poll(struct pollfd ufds
[], unsigned int nfds
, int timeout_ms
)
227 #ifdef HAVE_POLL_FINE
229 r
= poll(ufds
, nfds
, timeout_ms
);
230 } while((r
== -1) && (errno
== EINTR
));
231 #elif defined(CURL_HAVE_WSAPOLL)
232 r
= WSAPoll(ufds
, nfds
, timeout_ms
);
234 struct timeval timeout
;
235 struct timeval
*ptimeout
;
245 maxfd
= (curl_socket_t
)-1;
247 for (i
= 0; i
< nfds
; i
++) {
248 if (ufds
[i
].fd
== CURL_SOCKET_BAD
)
250 #ifndef USE_WINSOCK /* winsock sockets are not in range [0..FD_SETSIZE] */
251 if (ufds
[i
].fd
>= FD_SETSIZE
) {
256 if (ufds
[i
].fd
> maxfd
)
258 if (ufds
[i
].events
& POLLIN
)
259 FD_SET(ufds
[i
].fd
, &fds_read
);
260 if (ufds
[i
].events
& POLLOUT
)
261 FD_SET(ufds
[i
].fd
, &fds_write
);
262 if (ufds
[i
].events
& POLLERR
)
263 FD_SET(ufds
[i
].fd
, &fds_err
);
266 if (timeout_ms
< 0) {
267 ptimeout
= NULL
; /* wait forever */
269 timeout
.tv_sec
= timeout_ms
/ 1000;
270 timeout
.tv_usec
= (timeout_ms
% 1000) * 1000;
275 r
= select((int)maxfd
+ 1, &fds_read
, &fds_write
, &fds_err
, ptimeout
);
276 } while((r
== -1) && (Curl_sockerrno() == EINTR
));
284 for (i
= 0; i
< nfds
; i
++) {
286 if (ufds
[i
].fd
== CURL_SOCKET_BAD
)
288 if (FD_ISSET(ufds
[i
].fd
, &fds_read
))
289 ufds
[i
].revents
|= POLLIN
;
290 if (FD_ISSET(ufds
[i
].fd
, &fds_write
))
291 ufds
[i
].revents
|= POLLOUT
;
292 if (FD_ISSET(ufds
[i
].fd
, &fds_err
))
293 ufds
[i
].revents
|= POLLERR
;
294 if (ufds
[i
].revents
!= 0)
303 * This is a replacement for select() on the TPF platform.
304 * It is used whenever libcurl calls select().
305 * The call below to tpf_process_signals() is required because
306 * TPF's select calls are not signal interruptible.
308 * Return values are the same as select's.
310 int tpf_select_libcurl(int maxfds
, fd_set
* reads
, fd_set
* writes
,
311 fd_set
* excepts
, struct timeval
* tv
)
315 rc
= tpf_select_bsd(maxfds
, reads
, writes
, excepts
, tv
);
316 tpf_process_signals();