说一说packet poll 错误掩码的一个bug tcp udp packet poll细节有所不同 处理时需要注意

今天处理一个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  清除数据
复制代码

 

posted @   codestacklinuxer  阅读(363)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示