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>
This commit is contained in:
Родитель
83b98fb46f
Коммит
0884d7aa24
|
@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
|
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
|
||||||
(UNIXCB(skb).cred != siocb->scm->cred)) {
|
(UNIXCB(skb).cred != siocb->scm->cred)) {
|
||||||
skb_queue_head(&sk->sk_receive_queue, skb);
|
skb_queue_head(&sk->sk_receive_queue, skb);
|
||||||
|
sk->sk_data_ready(sk, skb->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
chunk = min_t(unsigned int, skb->len, size);
|
chunk = min_t(unsigned int, skb->len, size);
|
||||||
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
|
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
|
||||||
skb_queue_head(&sk->sk_receive_queue, skb);
|
skb_queue_head(&sk->sk_receive_queue, skb);
|
||||||
|
sk->sk_data_ready(sk, skb->len);
|
||||||
if (copied == 0)
|
if (copied == 0)
|
||||||
copied = -EFAULT;
|
copied = -EFAULT;
|
||||||
break;
|
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.. */
|
/* put the skb back if we didn't use it up.. */
|
||||||
if (skb->len) {
|
if (skb->len) {
|
||||||
skb_queue_head(&sk->sk_receive_queue, skb);
|
skb_queue_head(&sk->sk_receive_queue, skb);
|
||||||
|
sk->sk_data_ready(sk, skb->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
|
|
||||||
/* put message back and return */
|
/* put message back and return */
|
||||||
skb_queue_head(&sk->sk_receive_queue, skb);
|
skb_queue_head(&sk->sk_receive_queue, skb);
|
||||||
|
sk->sk_data_ready(sk, skb->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (size);
|
} while (size);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче