summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorAlexey Moiseytsev <himeraster@gmail.com>2011-11-21 13:35:25 +0000
committerDavid S. Miller <davem@davemloft.net>2011-11-26 16:34:22 -0500
commit0884d7aa24e15e72b3c07f7da910a13bb7df3592 (patch)
tree0b7257890d1e5a960f3205f94ab0a4d628ce7c3a /net
parent83b98fb46ff136945f9d06a9bf6e6aae2ffc37b3 (diff)
downloadlinux-3.10-0884d7aa24e15e72b3c07f7da910a13bb7df3592.tar.gz
linux-3.10-0884d7aa24e15e72b3c07f7da910a13bb7df3592.tar.bz2
linux-3.10-0884d7aa24e15e72b3c07f7da910a13bb7df3592.zip
AF_UNIX: Fix poll blocking problem when reading from a stream socket
poll() call may be blocked by concurrent reading from the same stream socket. Signed-off-by: Alexey Moiseytsev <himeraster@gmail.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/unix/af_unix.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 466fbcc5cf7..b595a3d8679 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
(UNIXCB(skb).cred != siocb->scm->cred)) {
skb_queue_head(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
break;
}
} else {
@@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
chunk = min_t(unsigned int, skb->len, size);
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
skb_queue_head(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
if (copied == 0)
copied = -EFAULT;
break;
@@ -1991,6 +1993,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
/* put the skb back if we didn't use it up.. */
if (skb->len) {
skb_queue_head(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
break;
}
@@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
/* put message back and return */
skb_queue_head(&sk->sk_receive_queue, skb);
+ sk->sk_data_ready(sk, skb->len);
break;
}
} while (size);