linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* poll() incompatability with POSIX.1-2001
@ 2002-10-14 14:58 Jogchem de Groot
  2002-10-14 15:14 ` Richard B. Johnson
  0 siblings, 1 reply; 6+ messages in thread
From: Jogchem de Groot @ 2002-10-14 14:58 UTC (permalink / raw)
  To: linux-kernel

Hello,

There's an incompatability with the poll() implementation in the
linux-2.4 kernel. (Tried 2.4.18).

According to the POSIX.1-2001 standard select() and poll() should
return writability (POLLOUT) when connect() initated on a non-blocking
socket asynchronously completes.

http://www.opengroup.org/onlinepubs/007904975/functions/connect.html

"If the connection cannot be established immediately and O_NONBLOCK is set
for the file descriptor for the socket, connect() shall fail and set errno to
[EINPROGRESS], but the connection request shall not be aborted, and the
connection shall be established asynchronously. Subsequent calls to connect()
for the same socket, before the connection is established, shall fail and set
errno to [EALREADY].

When the connection has been established asynchronously, select() and poll()
shall indicate that the file descriptor for the socket is ready for writing."

On linux-2.4 i noticed the following behaviour:

On connect() success select() returns writability for the socket.
On connect() failure select() returns readability and writability for the
socket.

This behaviour is according to the specification.

However with poll() (with events=POLLIN|POLLOUT) i get the following
behaviour:

On connect() success poll() returns POLLOUT in revents.
On connect() failure poll() returns POLLIN|POLLHUP|POLLERR in revents.

It does not set the POLLOUT bit here..

I hope somebody will take a closer look at this. It doesnt seem to require a
big fix at all..

Thank you,
    bighawk

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: poll() incompatability with POSIX.1-2001
  2002-10-14 14:58 poll() incompatability with POSIX.1-2001 Jogchem de Groot
@ 2002-10-14 15:14 ` Richard B. Johnson
  2002-10-14 17:13   ` Jogchem de Groot
  2002-10-15  3:36   ` Geoffrey Lee
  0 siblings, 2 replies; 6+ messages in thread
From: Richard B. Johnson @ 2002-10-14 15:14 UTC (permalink / raw)
  To: Jogchem de Groot; +Cc: linux-kernel

On Mon, 14 Oct 2002, Jogchem de Groot wrote:

> Hello,
> 
> There's an incompatability with the poll() implementation in the
> linux-2.4 kernel. (Tried 2.4.18).
> 
> According to the POSIX.1-2001 standard select() and poll() should
> return writability (POLLOUT) when connect() initated on a non-blocking
> socket asynchronously completes.
> 
> http://www.opengroup.org/onlinepubs/007904975/functions/connect.html
> 
> "If the connection cannot be established immediately and O_NONBLOCK is set
> for the file descriptor for the socket, connect() shall fail and set errno to
> [EINPROGRESS], but the connection request shall not be aborted, and the
> connection shall be established asynchronously. Subsequent calls to connect()
> for the same socket, before the connection is established, shall fail and set
> errno to [EALREADY].
> 
> When the connection has been established asynchronously, select() and poll()
> shall indicate that the file descriptor for the socket is ready for writing."
> 
> On linux-2.4 i noticed the following behaviour:
> 
> On connect() success select() returns writability for the socket.
> On connect() failure select() returns readability and writability for the
> socket.
> 
> This behaviour is according to the specification.
> 
> However with poll() (with events=POLLIN|POLLOUT) i get the following
> behaviour:
> 
> On connect() success poll() returns POLLOUT in revents.
> On connect() failure poll() returns POLLIN|POLLHUP|POLLERR in revents.
> 
> It does not set the POLLOUT bit here..

This is a failure to connect! The socket is therefore not ready for
writing  or reading -ever. This behavior may not be correct, not
because of a failure to set the POLLOUT bit, but because the POLLIN
bit is set. Check if this is really true. I can't duplicate this
on 2.4.18 here because it's hard to get a deferred connect with my
setup.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.18 on an i686 machine (797.90 BogoMips).
The US military has given us many words, FUBAR, SNAFU, now ENRON.
Yes, top management were graduates of West Point and Annapolis.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: poll() incompatability with POSIX.1-2001
  2002-10-14 15:14 ` Richard B. Johnson
@ 2002-10-14 17:13   ` Jogchem de Groot
  2002-10-15  3:36   ` Geoffrey Lee
  1 sibling, 0 replies; 6+ messages in thread
From: Jogchem de Groot @ 2002-10-14 17:13 UTC (permalink / raw)
  To: linux-kernel; +Cc: root

Hello, 

This is a failure to connect! The socket is therefore not ready for
writing  or reading -ever. This behavior may not be correct, not
because of a failure to set the POLLOUT bit, but because the POLLIN
bit is set. Check if this is really true. I can't duplicate this
on 2.4.18 here because it's hard to get a deferred connect with my
setup.

It's really true:..

Here is some strace output:

Case where connect() succeeds:

connect(3, {sin_family=AF_INET, sin_port=htons(111), 
sin_addr=inet_addr("127.0.0.1")}}, 16) = -1 EINPROGRESS (Operation now in 
progress)
poll([{fd=3, events=POLLIN|POLLOUT, revents=POLLOUT}], 1, -1) = 1
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0

As you can see SO_ERROR returns '0', connection succeeded.

Case where connect() fails:

connect(3, {sin_family=AF_INET, sin_port=htons(110), 
sin_addr=inet_addr("127.0.0.1")}}, 16) = -1 EINPROGRESS (Operation now in 
progress)
poll([{fd=3, events=POLLIN|POLLOUT, revents=POLLIN|POLLERR|POLLHUP}], 1, -1) 
= 1
getsockopt(3, SOL_SOCKET, SO_ERROR, [111], [4]) = 0

As you can see SO_ERROR returns '111', connection failed.

   bighawk

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: poll() incompatability with POSIX.1-2001
  2002-10-14 15:14 ` Richard B. Johnson
  2002-10-14 17:13   ` Jogchem de Groot
@ 2002-10-15  3:36   ` Geoffrey Lee
  2002-10-15  7:47     ` Jogchem de Groot
  1 sibling, 1 reply; 6+ messages in thread
From: Geoffrey Lee @ 2002-10-15  3:36 UTC (permalink / raw)
  To: Richard B. Johnson; +Cc: Jogchem de Groot, linux-kernel

> > 
> > When the connection has been established asynchronously, select() and poll()
> > shall indicate that the file descriptor for the socket is ready for writing."
> > 
> > On linux-2.4 i noticed the following behaviour:
> > 
> > On connect() success select() returns writability for the socket.
> > On connect() failure select() returns readability and writability for the
> > socket.
> > 
> > This behaviour is according to the specification.
> > 
> > However with poll() (with events=POLLIN|POLLOUT) i get the following
> > behaviour:
> > 
> > On connect() success poll() returns POLLOUT in revents.
> > On connect() failure poll() returns POLLIN|POLLHUP|POLLERR in revents.
> > 
> > It does not set the POLLOUT bit here..
> 
> This is a failure to connect! The socket is therefore not ready for
> writing  or reading -ever. This behavior may not be correct, not
> because of a failure to set the POLLOUT bit, but because the POLLIN
> bit is set. Check if this is really true. I can't duplicate this
> on 2.4.18 here because it's hard to get a deferred connect with my
> setup.
> 


Hello!



I have done some experimentation.


First I used telnet to verify that the host xx.xx.xx.xx on port 80 is
up and listening.  We verify that this is true.

Then, we run a test program.

The test program creates a TCP socket which will connect to a given host
on a given port then use the fcntl() call to set the non-blocking bit.

We then use connect() to connect to the host.  We verify that the errno
is indeed EINPROGRESS.

We then use poll with an events member set to POLLIN | POLLOUT.


This is the result on a return from poll().

glee@orion ~/tmp $ ./poll-new -h xx.xx.xx.xx -p 80
connect
connect: INPROGRESS
poll: POLLOUT is set
terminating
glee@orion ~/tmp $


So, POLLOUT is set.


Now, we try to connect to an invalid port.

n ~/tmp $ ./poll-new -h xx.xx.xx.xx -p 4
connect
connect: INPROGRESS
poll: POLLERR set
poll: POLLHUP set
poll: POLLOUT is set
terminating
glee@orion ~/tmp $


So, POLLOUT is set.

By the way, what constants should be defined when you do a #include <poll.h>?


A lot of them are not defined, those listed in the poll() document on 
the opengroup website, only POLLPRI and POLLIN, POLLOUT, POLLNVAL,
POLLHUP and POLLERR are defined.


POLLRDNORM, POLLRDBAND, POLLWRBAND, POLLWRNORM are not defined.


	-- G.
	

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: poll() incompatability with POSIX.1-2001
  2002-10-15  3:36   ` Geoffrey Lee
@ 2002-10-15  7:47     ` Jogchem de Groot
  2002-10-15 13:53       ` Geoffrey Lee
  0 siblings, 1 reply; 6+ messages in thread
From: Jogchem de Groot @ 2002-10-15  7:47 UTC (permalink / raw)
  To: Geoffrey Lee; +Cc: linux-kernel

On Tuesday 15 October 2002 05:36, you wrote:

> This is the result on a return from poll().
>
> glee@orion ~/tmp $ ./poll-new -h xx.xx.xx.xx -p 80
> connect
> connect: INPROGRESS
> poll: POLLOUT is set
> terminating
> glee@orion ~/tmp $
>
>
> So, POLLOUT is set.
>
>
> Now, we try to connect to an invalid port.
>
> n ~/tmp $ ./poll-new -h xx.xx.xx.xx -p 4
> connect
> connect: INPROGRESS
> poll: POLLERR set
> poll: POLLHUP set
> poll: POLLOUT is set
> terminating
> glee@orion ~/tmp $
>
>
> So, POLLOUT is set.

Hello, on what version did you try this? I've tried this now on 
Linux-2.4.18 and Linux-2.4.19 and both give the behaviour i described 
previously (No POLLOUT set).

The simple test program i used is as follows:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <errno.h>

main(int argc, char **argv) {
    int sd,flags,stat,len=sizeof(int);
    struct sockaddr_in sin;
    struct pollfd pfd;

    memset(&sin, 0, sizeof(sin));

    sd = socket(AF_INET, SOCK_STREAM, 0);
    fcntl(sd, F_SETFL, fcntl(sd, F_GETFL, 0) | O_NONBLOCK);

    sin.sin_addr.s_addr = htonl(0x7f000001);
    sin.sin_port = htons(atoi(argv[1]));
    sin.sin_family = AF_INET;

    if(connect(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1 && errno == 
EINPROGRESS)
        printf("connect returned EINPROGRESS\n");

    pfd.fd = sd;
    pfd.events = POLLIN | POLLOUT;
    pfd.revents = 0;

    poll(&pfd, 1, -1);
    getsockopt(sd, SOL_SOCKET, SO_ERROR, &stat, &len);
    printf("%s\n", stat ? "failed" : "succeeded");
    printf("returned events: %hd\n", pfd.revents);
}

    bighawk


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: poll() incompatability with POSIX.1-2001
  2002-10-15  7:47     ` Jogchem de Groot
@ 2002-10-15 13:53       ` Geoffrey Lee
  0 siblings, 0 replies; 6+ messages in thread
From: Geoffrey Lee @ 2002-10-15 13:53 UTC (permalink / raw)
  To: Jogchem de Groot; +Cc: linux-kernel

> Hello, on what version did you try this? I've tried this now on 
> Linux-2.4.18 and Linux-2.4.19 and both give the behaviour i described 
> previously (No POLLOUT set).
> 


Ah, you are indeed right.  I had a typo in my test code (trailing semi
colon).

So POLLIN | POLLERR | POLLHUP flags are for the revents member.



	-- G.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-10-15 13:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-14 14:58 poll() incompatability with POSIX.1-2001 Jogchem de Groot
2002-10-14 15:14 ` Richard B. Johnson
2002-10-14 17:13   ` Jogchem de Groot
2002-10-15  3:36   ` Geoffrey Lee
2002-10-15  7:47     ` Jogchem de Groot
2002-10-15 13:53       ` Geoffrey Lee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).