You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Eric van der Maarel <er...@nedap.com> on 2011/06/24 10:12:17 UTC
Re: 100% cpu with APR on Windows
On 05/29/2011 10:53 PM, Jeff Trawick wrote:
> On Fri, May 27, 2011 at 3:59 PM, Justin Erenkrantz
> <ju...@erenkrantz.com> wrote:
>> On Fri, May 27, 2011 at 9:48 AM,<tr...@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.vandermaarel@nedap.com |
-------------------------------------------^[ZZ