Re: Linux poll() <sigh> again

From: Eric Dumazet
Date: Fri May 12 2006 - 11:06:04 EST


linux-os (Dick Johnson) a écrit :
On Fri, 12 May 2006, jimmy wrote:

Robert Hancock wrote:
linux-os (Dick Johnson) wrote:
POLLHUP means "The device has been disconnected." This would obviously
be appropriate for a device such as a serial line or TTY, etc. but for a
socket it is less obvious that this return value is appropriate.

Hardly "less obvious". SunOs has returned POLLHUP as has other
Unixes like Interactive, from which the software was ported. It
went from Interactive, to SunOs, to Linux. Linux was the first
OS that required the hack. This was reported several years ago
and I was simply excoriated for having the audacity to report
such a thing. So, I just implemented a hack. Now the hack is
biting me. It's about time for poll() to return the correct
stuff.
The standard doesn't require that a close on a socket should report
POLLHUP. Thus this behavior may differ between UNIX implementations. If
your software is requiring a POLLHUP to indicate the socket is closed I
think it is being unnecessarily picky since read returning 0 universally
indicates that the connection has been closed. Such are the compromises
that are sometimes required to write portable software.

This is from the Linux man-page shipped with recent distributions


SOCKET(7) Linux ProgrammerâEUR(tm)s Manual SOCKET(7)



+--------------------------------------------------------------------+
| I/O events |
+-----------+-----------+--------------------------------------------+
|Event | Poll flag | Occurrence |
+-----------+-----------+--------------------------------------------+
|Read | POLLIN | New data arrived. |
+-----------+-----------+--------------------------------------------+
|Read | POLLIN | A connection setup has been completed (for |
| | | connection-oriented sockets) |
+-----------+-----------+--------------------------------------------+
|Read | POLLHUP | A disconnection request has been initiated |
| | | by the other end. |
+-----------+-----------+--------------------------------------------+
|Read | POLLHUP | A connection is broken (only for connec- |
| | | tion-oriented protocols). When the socket |
| | | is written SIGPIPE is also sent. |
+-----------+-----------+--------------------------------------------+
|Write | POLLOUT | Socket has enough send buffer space for |
| | | writing new data. |
+-----------+-----------+--------------------------------------------+
|Read/Write | POLLIN| | An outgoing connect(2) finished. |
| | POLLOUT | |
+-----------+-----------+--------------------------------------------+
|Read/Write | POLLERR | An asynchronous error occurred. |
+-----------+-----------+--------------------------------------------+
|Read/Write | POLLHUP | The other end has shut down one direction. |
+-----------+-----------+--------------------------------------------+
|Exception | POLLPRI | Urgent data arrived. SIGURG is sent then. |
+-----------+-----------+--------------------------------------------+


If linux doesn't support POLLHUP, then it shouldn't be documented.
I got the same king of crap^M^M^M^Mresponse the last time I reported
this __very__ __obvious__ defect! The information is available
in the kernel. It should certainly report it, just like other
operating systems do, including <shudder> wsock32.
Hi Dick

On socket disconnection, POLLIN set in poll()->revents and recv() returning 0 is the only portable and reliable method.

This is well explained in Stevens book (The absolute reference imho). It was writen well before Linus wrote a single line of C code.

If you dont have this book (that would be a shame !!! )

Please refer to http://www.opengroup.org/onlinepubs/000095399/functions/poll.html

POLLHUP

The device has been disconnected. This event and POLLOUT are
mutually-exclusive; a stream can never be writable if a hangup has
occurred. However, this event and POLLIN, POLLRDNORM, POLLRDBAND, or
POLLPRI are not mutually-exclusive. This flag is only valid in the
/revents/ bitmask; it shall be ignored in the /events/ member.

So you should not set POLLHUP in the mem->pfd.events member, since POLLHUP is non maskable.

Also you might find this interesting : http://www.greenend.org.uk/rjk/2001/06/poll.html

More over this comment found in the linux kernel (file net/ipv4/tcp.c) is quite good :

/*
* POLLHUP is certainly not done right. But poll() doesn't
* have a notion of HUP in just one direction, and for a
* socket the read side is more interesting.
*
* Some poll() documentation says that POLLHUP is incompatible
* with the POLLOUT/POLLWR flags, so somebody should check this
* all. But careful, it tends to be safer to return too many
* bits than too few, and you can easily break real applications
* if you don't tell them that something has hung up!
*
* Check-me.
*
* Check number 1. POLLHUP is _UNMASKABLE_ event (see UNIX98 and
* our fs/select.c). It means that after we received EOF,
* poll always returns immediately, making impossible poll() on write()
* in state CLOSE_WAIT. One solution is evident --- to set POLLHUP
* if and only if shutdown has been made in both directions.
* Actually, it is interesting to look how Solaris and DUX
* solve this dilemma. I would prefer, if PULLHUP were maskable,
* then we could set it on SND_SHUTDOWN. BTW examples given
* in Stevens' books assume exactly this behaviour, it explains
* why PULLHUP is incompatible with POLLOUT. --ANK
*
* NOTE. Check for TCP_CLOSE is added. The goal is to prevent
* blocking on fresh not-connected or disconnected socket. --ANK
*/
if (sk->sk_shutdown == SHUTDOWN_MASK || sk->sk_state == TCP_CLOSE)
mask |= POLLHUP;


So basically a POLLHUP could be stick in revent if POLLOUT was not given in event, but it would be of litle interest...

Eric



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/