Skip to content

Commit

Permalink
tipc: correct problems with misleading flags returned using poll()
Browse files Browse the repository at this point in the history
Prevent TIPC from incorrectly setting returned flags to poll()
in the following cases:

- an unconnected socket no longer indicates that it is always readable

- an unconnected, connecting, or listening socket no longer indicates
  that it is always writable

Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Allan Stephens authored and David S. Miller committed Aug 18, 2010
1 parent 35997e3 commit f662c07
Showing 1 changed file with 40 additions and 21 deletions.
61 changes: 40 additions & 21 deletions net/tipc/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,36 +429,55 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
* to handle any preventable race conditions, so TIPC will do the same ...
*
* TIPC sets the returned events as follows:
* a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty
* or if a connection-oriented socket is does not have an active connection
* (i.e. a read operation will not block).
* b) POLLOUT is set except when a socket's connection has been terminated
* (i.e. a write operation will not block).
* c) POLLHUP is set when a socket's connection has been terminated.
*
* IMPORTANT: The fact that a read or write operation will not block does NOT
* imply that the operation will succeed!
*
* socket state flags set
* ------------ ---------
* unconnected no read flags
* no write flags
*
* connecting POLLIN/POLLRDNORM if ACK/NACK in rx queue
* no write flags
*
* connected POLLIN/POLLRDNORM if data in rx queue
* POLLOUT if port is not congested
*
* disconnecting POLLIN/POLLRDNORM/POLLHUP
* no write flags
*
* listening POLLIN if SYN in rx queue
* no write flags
*
* ready POLLIN/POLLRDNORM if data in rx queue
* [connectionless] POLLOUT (since port cannot be congested)
*
* IMPORTANT: The fact that a read or write operation is indicated does NOT
* imply that the operation will succeed, merely that it should be performed
* and will not block.
*/

static unsigned int poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
u32 mask;
u32 mask = 0;

poll_wait(file, sk_sleep(sk), wait);

if (!skb_queue_empty(&sk->sk_receive_queue) ||
(sock->state == SS_UNCONNECTED) ||
(sock->state == SS_DISCONNECTING))
mask = (POLLRDNORM | POLLIN);
else
mask = 0;

if (sock->state == SS_DISCONNECTING)
mask |= POLLHUP;
else
mask |= POLLOUT;
switch ((int)sock->state) {
case SS_READY:
case SS_CONNECTED:
if (!tipc_sk_port(sk)->congested)
mask |= POLLOUT;
/* fall thru' */
case SS_CONNECTING:
case SS_LISTENING:
if (!skb_queue_empty(&sk->sk_receive_queue))
mask |= (POLLIN | POLLRDNORM);
break;
case SS_DISCONNECTING:
mask = (POLLIN | POLLRDNORM | POLLHUP);
break;
}

return mask;
}
Expand Down

0 comments on commit f662c07

Please sign in to comment.