On 05/29/2011 10:53 PM, Jeff Trawick wrote:
On Fri, May 27, 2011 at 3:59 PM, Justin Erenkrantz
<jus...@erenkrantz.com> wrote:
On Fri, May 27, 2011 at 9:48 AM,<traw...@gmail.com> wrote:
Can you outline the idioms you refer to that prefer a select()
implementation?
iow, how different are they from
apr_socket_create
set socket nonblocking with no timeout
apr_socket_connect()
apr_pollset_poll()
That's all serf is doing. With WSAPoll(), if you connect to a port
via a non-blocking socket that there is no listener on, WSAPoll()
never sends any indication. However, select() lets you know that the
earlier connect() failed. Given the pretty isolated test case in the
forum earlier, I do think this is an underlying issue with WSAPoll() -
but enough of an issue, it shouldn't be the default unless someone can
find a way to get WSAPoll() to report failure... -- justin
no-can-do AFAICT; there's literally NOTHING you can put in .events
which results in anything reported in .revents after ECONNREFUSED
your two cases are the only reports of WSAPoll() problems I know of in
the last year (since 1.4.x was released, making WSAPoll() the
default); still, it seems probable that more code works with a
select()-based implementation
a new WSAEVENT-based implementation may be the long term solution
(FD_CONNECT events would have to be mapped to something the app would
ask for; presumably FD_CLOSE events would map to POLLHUP, which was
the select() issue which started this thread)
I propose a patch for impl_pollset_poll() in select.c (the poller impl
based on select(), used on Windows XP).
The idea is to test all sockets that are kept by select() in the read
set, for data with a peeking recv() call. When the call to recv() for a
socket returns 0, no data read, we set the APR_POLLHUP flag in the
return event of the pollset result_set. And we set the APR_POLLERR flag
when result < 0.
This works since the socket was kept in the read set by select(), either
since there's data or since the socket was disconnected.
I'm not sure about the conditions under which recv() can return 0
though... (e.g. socket has not yet accept()ed an incoming connection
request? or data is available but for some reason recv() still reads no
data and returns 0?).
Test results so far are positive.
Here's the proposed code, with changes/additions in lines 6-12:
1 if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) ||
2 FD_ISSET(fd, &exceptset)) {
3 pollset->p->result_set[j] = pollset->p->query_set[i];
4 pollset->p->result_set[j].rtnevents = 0;
5 if (FD_ISSET(fd, &readset)) {
6 r = recv(fd, buf, 8, MSG_PEEK); // 8 byte buffer
7 if (r == 0) {
8 pollset->p->result_set[j].rtnevents |= APR_POLLHUP;
9 }
10 else if (r < 0) {
11 pollset->p->result_set[j].rtnevents |= APR_POLLERR;
12 }
13 pollset->p->result_set[j].rtnevents |= APR_POLLIN;
14 }
15 if (FD_ISSET(fd, &writeset)) {
16 pollset->p->result_set[j].rtnevents |= APR_POLLOUT;
17 }
18 if (FD_ISSET(fd, &exceptset)) {
19 pollset->p->result_set[j].rtnevents |= APR_POLLERR;
20 }
21 j++;
Regards,
Eric
--
-------------------------------------------
| Eric van der Maarel |
| NEDAP IDEAS |
| eric.vandermaa...@nedap.com |
-------------------------------------------^[ZZ