今天处理一个cpu标高的bug,原因:在poll 返回后将error事件当做POLLIN事件处理,fd 一直都在唤醒线程处理,但是rcv的时候没有数据;
unsigned int datagram_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
unsigned int mask;
sock\_poll\_wait(file, sk\_sleep(sk), wait);
mask = 0;
/\* exceptional events? \*/
if (sk->sk\_err || !skb\_queue\_empty(&sk->sk\_error\_queue))
mask |= POLLERR;
if (sk->sk\_shutdown & RCV\_SHUTDOWN)
mask |= POLLRDHUP | POLLIN | POLLRDNORM;
if (sk->sk\_shutdown == SHUTDOWN\_MASK)
mask |= POLLHUP;
static unsigned int packet_poll(struct file *file, struct socket *sock,
poll_table *wait)
{
struct sock *sk = sock->sk;
struct packet_sock *po = pkt_sk(sk);
unsigned int mask = datagram_poll(file, sock, wait);
spin\_lock\_bh(&sk->sk\_receive\_queue.lock);
if (po->rx\_ring.pg\_vec) {
if (!packet\_previous\_rx\_frame(po, &po->rx\_ring,
TP\_STATUS\_KERNEL))
mask |= POLLIN | POLLRDNORM;
}
从代码中可以看到(sk->sk_err || !skb_queue_empty(&sk->sk_error_queue) 只要满足一个条件就会唤醒进程,但是由于sk_error_queue 的数据一直都没有清楚,所以会导致一直唤醒进程。但是mmap-packet读取数据时,又没有数据
那么怎么处理呢?
目前简单的处理方式为:在rcvmsg时 带上MSG_ERRQUEUE 主动收取错误报文
或者
case SO_ERROR:
v.val = -sock_error(sk);
if (v.val == 0)
v.val = xchg(&sk->sk_err_soft, 0);
break;
//使用getsockopt 获取错误标志
case IP_RECVERR:
inet->recverr = !!val;
if (!val)
skb_queue_purge(&sk->sk_error_queue);
break;
//使用 ip_setsockopt 清除数据
手机扫一扫
移动阅读更方便
你可能感兴趣的文章