2001-03-14 02:00:24

by Jeffrey Butler

[permalink] [raw]
Subject: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

Hi,
I've noticed that poll() calls on IPv4 sockets do
not behave the same under linux 2.4 vs. linux 2.2.14.
Linux 2.4 will return POLLHUP for a socket that is not
connected (and has never been connected) while Linux
2.2 will not.
The following example program demonstrates the
problem when it's run under linux 2.4:

---
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>

int main(
int argc,
char **argv)
{
int s;
int rv;
struct pollfd pfd;

s = socket(PF_INET,SOCK_STREAM,0);
pfd.fd = s;
pfd.events = 0;
rv = poll(&pfd,1,1);
printf("rv = %d
",rv);
if(pfd.revents&POLLIN) {printf("pollin
");}
if(pfd.revents&POLLPRI){printf("pollpri
");}
if(pfd.revents&POLLOUT){printf("pollout
");}
if(pfd.revents&POLLERR){printf("pollerr
");}
if(pfd.revents&POLLHUP){printf("pollhup
");}
close(s);
}

(copy text to file, run 'gcc -o example example.c', to
compile)

Under Linux 2.4 (specifically 2.4.1) this program will
output:
rv = 0
pollhup

Under Linux 2.2.14 it outputs:
rv = 0

Other operating systems (not that they are necessarily
correct) also output the same as Linux 2.2.14. I
tried this on FreeBSD 4.4.1, Solaris 5.7 (on a SPARC),
and Windows 2000 with Cygwin 1.1.7.

I'm not sure what POSIX says about this behavior...

This can be traced back to the poll implementation in
the Linux kernel:

In 2.2.14:
net/ipv4/tcp.c[line 580]:
if (sk->shutdown & RCV_SHUTDOWN)
mask |= POLLHUP;

vs.
In 2.4.1:
net/ipv4/tcp.c[line 586]:
* NOTE. Check for TCP_CLOSE is added. The goal is to
prevent
* blocking on fresh not-connected or disconnected
socket. --ANK
*/
if (sk->shutdown == SHUTDOWN_MASK || sk->state ==
TCP_CLOSE)
mask |= POLLHUP;

The behavior observed at user-level matches his
comment as POLLHUP is returned for a fresh
not-connected socket.

What's the reasoning for this change in behavior? I
know of ways of getting around it, but I wanted to
bring this to everyone's attention.

thanks,
-jeff



__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - Buy the things you want at great prices.
http://auctions.yahoo.com/


2001-03-14 02:08:05

by David Miller

[permalink] [raw]
Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)


Jeffrey Butler writes:
> I've noticed that poll() calls on IPv4 sockets do
> not behave the same under linux 2.4 vs. linux 2.2.14.
> Linux 2.4 will return POLLHUP for a socket that is not
> connected (and has never been connected) while Linux
> 2.2 will not.
> The following example program demonstrates the
> problem when it's run under linux 2.4:

True, this behavior was changed from 2.2.x. We now match the behavior
of other svr4 systems, in particular Solaris. This new behavior in
2.4.x will not change.

Later,
David S. Miller
[email protected]

Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

[email protected] (David S. Miller) writes:

>Jeffrey Butler writes:
> > I've noticed that poll() calls on IPv4 sockets do
> > not behave the same under linux 2.4 vs. linux 2.2.14.
> > Linux 2.4 will return POLLHUP for a socket that is not
> > connected (and has never been connected) while Linux
> > 2.2 will not.
> > The following example program demonstrates the
> > problem when it's run under linux 2.4:

>True, this behavior was changed from 2.2.x. We now match the behavior
>of other svr4 systems, in particular Solaris. This new behavior in
>2.4.x will not change.

Hi,

but Jeffrey wrote:

--- cut ---
JB> Other operating systems (not that they are necessarily
JB> correct) also output the same as Linux 2.2.14. I
JB> tried this on FreeBSD 4.4.1, Solaris 5.7 (on a SPARC),
JB> and Windows 2000 with Cygwin 1.1.7.
--- cut ---

This is BSD, SysVR4 and an abomination all behaving like 2.2.x and not
2.4.x (which confuses the heck out of a poll()-using daemon
here... :-) )

I'd prefer not to have too many user space surprises in moving from
2.2 to 2.4.

Regards
Henning
--
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH [email protected]

Am Schwabachgrund 22 Fon.: 09131 / 50654-0 [email protected]
D-91054 Buckenhof Fax.: 09131 / 50654-20

2001-03-14 16:29:22

by Jeffrey Butler

[permalink] [raw]
Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

What version of Solaris should the poll() call behave
like? I tried the test program that I posted in the
original post on this thread on a couple of versions
of Solaris, and they all behaved like Linux 2.2, not
Linux 2.4.

The following version strings are from sysinfo on the
Solaris machines that I tested:

Machine 1:
CPU Type is sparcv8plus+vis
App Architecture is sparc
Kernel Architecture is sun4u
OS Name is SunOS
OS Version is 5.7
OS Distribution is Solaris 7 5/99
s998s_u2SunServer_09 SPARC
Kernel Version is SunOS Release 5.7 Version
Generic_106541-11 [UNIX(R) System V Release 4.0]

Machine 2:
SunOS xxx.xxx.xxx.xxx 5.5.1 Generic_103640-29 sun4u
sparc SUNW,Ultra-5_10.

Does Linux 2.4 poll() behave like Solaris 8 poll()
with respect to poll()? If I had access to a Solaris
8 machine I would have tested it because I realize the
Solaris versions are a bit out of date.

-jeff

--- "David S. Miller" <[email protected]> wrote:
>
> Jeffrey Butler writes:
> > I've noticed that poll() calls on IPv4 sockets
> do
> > not behave the same under linux 2.4 vs. linux
> 2.2.14.
> > Linux 2.4 will return POLLHUP for a socket that
> is not
> > connected (and has never been connected) while
> Linux
> > 2.2 will not.
> > The following example program demonstrates the
> > problem when it's run under linux 2.4:
>
> True, this behavior was changed from 2.2.x. We now
> match the behavior
> of other svr4 systems, in particular Solaris. This
> new behavior in
> 2.4.x will not change.
>
> Later,
> David S. Miller
> [email protected]


__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - Buy the things you want at great prices.
http://auctions.yahoo.com/

2001-03-14 19:55:57

by Alexey Kuznetsov

[permalink] [raw]
Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

Hello!

> True, this behavior was changed from 2.2.x. We now match the behavior
> of other svr4 systems, in particular Solaris.

Damn, we did not test behaviour on absolutely new clean never
connected socket... Solaris really may return 0 on it.

However, looking from other hand the issue looks as absolutely
academic and not related to practice in any way.

Alexey

2001-03-15 04:01:18

by Jeffrey Butler

[permalink] [raw]
Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

Alexy wrote:
>> Damn, we did not test behaviour on absolutely new
>> clean never connected socket... Solaris really may
>> return 0 on it.
>>
>> However, looking from other hand the issue looks as
>> absolutely academic and not related to practice in
>> any way.

Hi,
I'm not sure this issue is really that academic. In
fact, it's one of those nitty-gritty, annoying details
that academics tend to ignore :). Anyway, I'm looking
at this from a very pragmatic standpoint. I'd like to
minimize the complexity and the number of special
cases when trying to support an application on several
different platforms. If other popular Unix OS's
behave this way I definely understand the reasoning,
but it seems that at least Solaris 7 does not...
Sure, workarounds exist, but they just complicates
things.

-jeff

__________________________________________________
Do You Yahoo!?
Yahoo! Auctions - Buy the things you want at great prices.
http://auctions.yahoo.com/

2001-03-15 17:23:27

by Alexey Kuznetsov

[permalink] [raw]
Subject: Re: poll() behaves differently in Linux 2.4.1 vs. Linux 2.2.14 (POLLHUP)

Hello!

> Sure, workarounds exist, but they just complicates
> things.

Working around --- what?

An example of application hitting the case is enough to make
me completely agreed.

But genarally we are not going to match any os and even yourselves
yesterday or tomorrow in the cases when behaviour is truly undefined
and the answer is meaningless. For me any solution from retunring 0
or returning POLLHUO to killing offending application or generating
an answer using random number generator look equally good, acceptable
and 100% compatible in this case. 8)

Alexey