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

Reply via email to