Re: UDP recvmsg blocks after select(), 2.6 bug?

David S. Miller
2004-10-07T22:30:48Z

On Thu, 07 Oct 2004 16:24:13 -0600
Chris Friesen <cfriesen@nortelnetworks.com> wrote:

> I believe you misread what I said. Just before the above quote, I said "We are
> discussing the case where the socket is nonblocking and the udp checksum is
> corrupt, right? "

And in that case we return -EAGAIN and always have.

> What I had in mind was that the non-blocking file descriptor have select()
> return without verifying the checksum, and if it was discovered to be bad at
> recvmsg() time, we return EAGAIN.

That's what we do. In net/ipv4/udp.c:udp_recvmsg()

if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
} else if (msg->msg_flags&MSG_TRUNC) {
if (__udp_checksum_complete(skb))
goto csum_copy_err;
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
} else {
err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);

if (err == -EINVAL)
goto csum_copy_err;
}
...
csum_copy_err:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);

/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
spin_lock_irq(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
spin_unlock_irq(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}

skb_free_datagram(sk, skb);

if (noblock)
return -EAGAIN;
goto try_again;

If socket is non-blocking, return -EAGAIN, else go back to "try_again"
where we block on packet arrival or error.