You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by Ruediger Pluem <rp...@apache.org> on 2006/08/02 23:06:24 UTC
[Fwd: Re: How to detect is the socket is still open]
Reposting what I sent to Mladen in private. Just missed that
his address was in to and not dev@apr.apache.org :-)
-------- Original Message --------
Subject: Re: How to detect is the socket is still open
Date: Wed, 02 Aug 2006 21:57:36 +0200
From: Ruediger Pluem <rp...@apache.org>
To: Mladen Turk <mt...@apache.org>
References: <44...@apache.org>
On 08/02/2006 01:42 PM, Mladen Turk wrote:
>
> My question is, if someone is aware of the
> smarter mechanism for checking the socket
> connection, and if we could add the function
> for that inside APR.
What does poll (with timeout zero) return in the case that the socket has been closed?
Regards
Rüdiger
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Alexander Lazic <al...@none.at>.
On Mit 16.08.2006 08:55, Joe Orton wrote:
>
>POLLERR would only be set for an RST and "exceptional conditions"; the
>same applies to select()+the exceptfds array AFAIK.
>
>There is some inconsistency with handling FIN and sockets across
>platforms: http://www.greenend.org.uk/rjk/2001/06/poll.html but yes
>you'd generally expect POLLIN for "you can read EOF".
On curl-library list there was a similar thread about poll on MacOsX:
'poll & Mac OS X 10.4'
http://curl.haxx.se/mail/lib-2005-05/index.html#118
There was a link to mac develop site:
http://developer.apple.com/technotes/tn2002/tn2071.html
---
.
.
poll
This API is not supported in Mac OS X, instead, the function select is
used. The select function does synchronous I/O multiplexing, similar to
poll. This API is located in the following header files: <sys/types.h>,
<sys/time.h>, <unistd.h> The select API is defined as follow:
---
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
---
The behavior of select is not exactly the same as poll, so you will have
to alter your code. select gives you a number of macros to manipulate
the file descriptor returned, which is done differently in poll
An alternative to avoid changing your code is to use a wrapper around
select, such as fakepoll.h. Simply include the file fakepoll.h in your
code, and the library does the rest of the work. See
sealiesoftware.com/fakepoll.h for more information about fakepoll.h.
Note: fakepoll.h is a third-party library and not supported by Apple.
.
.
---
regards
Alex
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Joe Orton <jo...@redhat.com>.
On Wed, Aug 16, 2006 at 06:24:37AM -0700, Justin Erenkrantz wrote:
> Back to our original question: how can we portably detect that the socket is
> still alive? We can't do a non-blocking read() either... -- justin
AFAIK the closure of the read direction of the socket is exposed only by
consuming the receive buffer until a read returns EOF. There is no way
to determine "is the next thing available to read going to be EOF"
except by actually doing the read/recv. (I guess recv/MSG_PEEK will tell
you without having to actually consume the EOF; not sure that makes any
difference though)
joe
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Davi Arnaut <da...@haxent.com.br>.
Em 16/08/2006, às 14:21, Davi Arnaut escreveu:
>
> Em 16/08/2006, às 12:49, Joe Orton escreveu:
>
>> On Wed, Aug 16, 2006 at 12:36:23PM -0300, Davi Arnaut wrote:
>>> Em 16/08/2006, às 11:00, Justin Erenkrantz escreveu:
>>>> Would a non-blocking read() followed by a poll()/select() be
>>>> useful?
>>>> We'd still get a 0 back from read() - but if it was the EOF,
>>>> would the
>>>> state of the socket change to be in the 'exceptional' state then
>>>> if we
>>>> repoll? -- justin
>>>
>>> Humm, read returning 0 is a EOF, you could also maybe
>>> getsockopt(SO_ERROR) on the socket to confirm the EOF.
>>
>> SO_ERROR will only give an error in cases where a read or write would
>> fail and set errno; that's not true for EOF.
>
> No, but moving on..
>
>>
>>> Select is a different beast because of the definition of what is
>>> a "exceptional condition" which may be pending error conditions
>>> or oob data. I think the "exception fd" of select is similar to a
>>> poll
>>> with POLLPRI mask, so it shoud'nt signal a connection reset.
>>
>> It's POLLERR, hopefully; that's how APR maps it anyway ;)
>
> It's POLLPRI, errors are not exceptional conditions.
Just to be clearer, a socket is considered to have an "exceptional
condition"
if a read would return OOB data without blocking or if there is a OOB
data mark
on the receive queue. Other exceptional conditions are protocol/
implementation
specific. There is no _standard_ way to detect EOF using select().
For example, the Linux select syscall defines/uses the fowling:
#define POLLIN_SET (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP |
POLLERR)
#define POLLOUT_SET (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR)
#define POLLEX_SET (POLLPRI)
So a socket in the readfds is also watched for a EOF.
--
Davi Arnaut
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Davi Arnaut <da...@haxent.com.br>.
Em 16/08/2006, às 12:49, Joe Orton escreveu:
> On Wed, Aug 16, 2006 at 12:36:23PM -0300, Davi Arnaut wrote:
>> Em 16/08/2006, às 11:00, Justin Erenkrantz escreveu:
>>> Would a non-blocking read() followed by a poll()/select() be useful?
>>> We'd still get a 0 back from read() - but if it was the EOF,
>>> would the
>>> state of the socket change to be in the 'exceptional' state then
>>> if we
>>> repoll? -- justin
>>
>> Humm, read returning 0 is a EOF, you could also maybe
>> getsockopt(SO_ERROR) on the socket to confirm the EOF.
>
> SO_ERROR will only give an error in cases where a read or write would
> fail and set errno; that's not true for EOF.
No, but moving on..
>
>> Select is a different beast because of the definition of what is
>> a "exceptional condition" which may be pending error conditions
>> or oob data. I think the "exception fd" of select is similar to a
>> poll
>> with POLLPRI mask, so it shoud'nt signal a connection reset.
>
> It's POLLERR, hopefully; that's how APR maps it anyway ;)
It's POLLPRI, errors are not exceptional conditions.
--
Davi Arnaut
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Joe Orton <jo...@redhat.com>.
On Wed, Aug 16, 2006 at 12:36:23PM -0300, Davi Arnaut wrote:
> Em 16/08/2006, às 11:00, Justin Erenkrantz escreveu:
> >Would a non-blocking read() followed by a poll()/select() be useful?
> >We'd still get a 0 back from read() - but if it was the EOF, would the
> >state of the socket change to be in the 'exceptional' state then if we
> >repoll? -- justin
>
> Humm, read returning 0 is a EOF, you could also maybe
> getsockopt(SO_ERROR) on the socket to confirm the EOF.
SO_ERROR will only give an error in cases where a read or write would
fail and set errno; that's not true for EOF.
> Select is a different beast because of the definition of what is
> a "exceptional condition" which may be pending error conditions
> or oob data. I think the "exception fd" of select is similar to a poll
> with POLLPRI mask, so it shoud'nt signal a connection reset.
It's POLLERR, hopefully; that's how APR maps it anyway ;)
joe
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Davi Arnaut <da...@haxent.com.br>.
Em 16/08/2006, às 11:00, Justin Erenkrantz escreveu:
> On 8/16/06, Davi Arnaut <da...@haxent.com.br> wrote:
>> The only portable way to "detect" a broken connection is using
>> SO_KEEPALIVE
>> or to write/read "ping" data through the socket -- which is what
>> keepalive does.
>
> How would SO_KEEPALIVE help? The other end is deliberately closing
> the connection and we need to know that.
It would help detect a broken connection, not a RST state.
> Would a non-blocking read() followed by a poll()/select() be useful?
> We'd still get a 0 back from read() - but if it was the EOF, would the
> state of the socket change to be in the 'exceptional' state then if we
> repoll? -- justin
Humm, read returning 0 is a EOF, you could also maybe
getsockopt(SO_ERROR) on the socket to confirm the EOF.
Upon receive of a RST the socket should move to the closed
state, and poll should return immediately if the POLLHUP mask
was passed for that socket, and SO_ERROR should be one of
ECONNREFUSED (syn sent)/EPIPE (close wait)/ECONNRESET
or none if the socket was already closed.
Select is a different beast because of the definition of what is
a "exceptional condition" which may be pending error conditions
or oob data. I think the "exception fd" of select is similar to a poll
with POLLPRI mask, so it shoud'nt signal a connection reset.
--
Davi Arnaut
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
On 8/16/06, Davi Arnaut <da...@haxent.com.br> wrote:
> The only portable way to "detect" a broken connection is using
> SO_KEEPALIVE
> or to write/read "ping" data through the socket -- which is what
> keepalive does.
How would SO_KEEPALIVE help? The other end is deliberately closing
the connection and we need to know that.
Would a non-blocking read() followed by a poll()/select() be useful?
We'd still get a 0 back from read() - but if it was the EOF, would the
state of the socket change to be in the 'exceptional' state then if we
repoll? -- justin
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Davi Arnaut <da...@haxent.com.br>.
Em 16/08/2006, às 10:24, Justin Erenkrantz escreveu:
> On Wed, Aug 16, 2006 at 08:55:44AM +0100, Joe Orton wrote:
>> POLLERR would only be set for an RST and "exceptional conditions";
>> the
>> same applies to select()+the exceptfds array AFAIK.
>>
>> There is some inconsistency with handling FIN and sockets across
>> platforms: http://www.greenend.org.uk/rjk/2001/06/poll.html but yes
>> you'd generally expect POLLIN for "you can read EOF".
>
> Back to our original question: how can we portably detect that the
> socket is
> still alive? We can't do a non-blocking read() either... -- justin
Hi,
The only portable way to "detect" a broken connection is using
SO_KEEPALIVE
or to write/read "ping" data through the socket -- which is what
keepalive does.
There is no other way around this, most network protocols are timeout
based.
--
Davi Arnaut
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
On Wed, Aug 16, 2006 at 08:55:44AM +0100, Joe Orton wrote:
> POLLERR would only be set for an RST and "exceptional conditions"; the
> same applies to select()+the exceptfds array AFAIK.
>
> There is some inconsistency with handling FIN and sockets across
> platforms: http://www.greenend.org.uk/rjk/2001/06/poll.html but yes
> you'd generally expect POLLIN for "you can read EOF".
Back to our original question: how can we portably detect that the socket is
still alive? We can't do a non-blocking read() either... -- justin
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Joe Orton <jo...@redhat.com>.
On Wed, Aug 16, 2006 at 12:01:34AM -0700, Justin Erenkrantz wrote:
> On that second update, there are often 15+ second pauses from svn.a.o
> that causes httpd to close the connection as its idle. But, when we
> want to reuse that connection later, serf does a pollset_poll() and it
> says that the connection is good to go. But, it's not and we get an 0
> from read(). This leads to a 'Premature EOF seen from server' error.
>
> Shouldn't select() be returning POLLERR in this case? Or, am I nuts?
> Are we hitting some type of stupidity in Darwin? -- justin
POLLERR would only be set for an RST and "exceptional conditions"; the
same applies to select()+the exceptfds array AFAIK.
There is some inconsistency with handling FIN and sockets across
platforms: http://www.greenend.org.uk/rjk/2001/06/poll.html but yes
you'd generally expect POLLIN for "you can read EOF".
joe
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Justin Erenkrantz <ju...@erenkrantz.com>.
On 8/3/06, Gonzalo Paniagua Javier <go...@gmail.com> wrote:
> > > It reports that the socket is readable.
> >
> > And when you read it, it returns EOF?
>
> Yes, it returns a 0.
Are you on Mac OS X by any chance?
I'm seeing this same thing with serf via apr_pollset_poll().
select() returns 5 (POLLIN & POLLOUT I think) - but by this point, the
local end has already received a remote FIN.
My repro case (ra_serf / serf / apr trunk) is:
% svn co -r300000 http://svn.apache.org/repos/asf/httpd/httpd/trunk
% svn up -rHEAD trunk
On that second update, there are often 15+ second pauses from svn.a.o
that causes httpd to close the connection as its idle. But, when we
want to reuse that connection later, serf does a pollset_poll() and it
says that the connection is good to go. But, it's not and we get an 0
from read(). This leads to a 'Premature EOF seen from server' error.
Shouldn't select() be returning POLLERR in this case? Or, am I nuts?
Are we hitting some type of stupidity in Darwin? -- justin
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Gonzalo Paniagua Javier <go...@gmail.com>.
On 8/3/06, Ruediger Pluem <rp...@apache.org> wrote:
>
>
> On 08/03/2006 02:47 AM, Gonzalo Paniagua Javier wrote:
> >>
> >> What does poll (with timeout zero) return in the case that the socket
> >> has been closed?
> >
> >
> > It reports that the socket is readable.
>
> And when you read it, it returns EOF?
Yes, it returns a 0.
-Gonzalo
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Ruediger Pluem <rp...@apache.org>.
On 08/03/2006 02:47 AM, Gonzalo Paniagua Javier wrote:
>>
>> What does poll (with timeout zero) return in the case that the socket
>> has been closed?
>
>
> It reports that the socket is readable.
And when you read it, it returns EOF?
Regards
Rüdiger
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Gonzalo Paniagua Javier <go...@gmail.com>.
>
> What does poll (with timeout zero) return in the case that the socket has been closed?
It reports that the socket is readable.
-Gonzalo
Re: [Fwd: Re: How to detect is the socket is still open]
Posted by Mladen Turk <mt...@apache.org>.
Ruediger Pluem wrote:
> Reposting what I sent to Mladen in private. Just missed that
> his address was in to and not dev@apr.apache.org :-)
>
OK. Here is the new code used in mod_jk
It works for the selected set of platforms
(windows, linux, solaris)
Any comments about other platforms?
int jk_is_socket_connected(jk_sock_t sock)
{
fd_set fd;
struct timeval tv;
int rc;
FD_ZERO(&fd);
FD_SET(sock, &fd);
/* Wait one microsecond */
tv.tv_sec = 0;
tv.tv_usec = 1;
do {
rc = select((int)sock + 1, &fd, NULL, NULL, &tv);
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
errno = WSAGetLastError() - WSABASEERR;
#endif
} while (rc == -1 && errno == EINTR);
if (rc == 0) {
/* If we get a timeout, then we are still connected */
return 1;
}
else if (rc == 1) {
#if defined(WIN32) || (defined(NETWARE) && defined(__NOVELL_LIBC__))
u_long nr;
if (ioctlsocket(sock, FIONREAD, &nr) == 0) {
return nr == 0 ? 0 : 1;
}
#else
int nr;
if (ioctl(sock, FIONREAD, (void*)&nr) == 0) {
return nr == 0 ? 0 : 1;
}
#endif
}
return 0;
}