2

我遇到了一个奇怪的问题,来自 snmplib 的 snmp_synch_response() 的大量消息在大约三个小时内设法填满了 60GB 硬盘。这些消息都是“使用 snmp_sess_select_info2() 处理大型文件描述符”,有时每行重复一百多次。我仍在与客户合作,以​​找出如何在内部重现此问题,但我想我会在这里问一下,以防这是一个老问题,或者至少以某种方式被其他人看到。

这是基本的系统信息:8.1-RELEASE-p2 FreeBSD i386。NET-SNMP 版本是 5.5。

下面是我的代码关键部分的简化片段。代码首先创建一个包含已初始化但未打开的会话的任务列表。在其他地方,每个任务,最多一个小的限制(在这种情况下为 64 个),都被分叉,并且子进程使用 snmp_open() 打开 SNMP 会话套接字,依此类推。我已经搜索了 set()、get() 和 getnext() 中的每一个,并且确信它们都适当地调用了 snmp_close()——没有任何早期返回或其他跳过这些调用——所以我不认为我明确泄漏了任何套接字,但描述符必须由于某种原因而存在。这会为任何人敲响警钟吗?

for(…){
    …
    snmp_sess_init(&task->sess_info);
    addtask(taskList, task);
    …
}

…

for(task = taskList; task && nkids < maxkids; task = task->next){
    if(fork() == 0){
        set(task);
        get(task);
        getnext(task);
        …
    }
    nkids++;
}

void set(Task *task){
    …
    sess = snmp_open(&task->sess_info);
    …
    pdu = snmp_pdu_create(SNMP_MSG_SET);
    …
    status = snmp_synch_response(sess, pdu, &resp);
    // check return, retr
    snmp_close(sess);
}

void get(Task *task){
    …
    sess = snmp_open(sess_info);
    …
    pdu = snmp_pdu_create(SNMP_MSG_GET);
    …
    status = snmp_synch_response(sess, pdu, &resp);
    // check return, read variables
    snmp_close(sess);
}

void getnext(Task *task){
    …
    sess = snmp_open(sess_info);
    for(obj = task->objs; obj; obj = obj->next){
        …
        pdu = snmp_pdu_create(SNMP_MSG_GET);
        …
        status = snmp_synch_response(sess, pdu, &resp);
        // check return, read variables
    }
    snmp_close(sess);
}
4

2 回答 2

2

如果有人设法遇到类似的事情,这(不出所料)最终与 net-snmp 没有任何关系。每个子进程都通过自己的套接字与父进程通信。根据 fork() 的基本性质,父级的套接字列表被复制到每个子级;解决方案只是在子代码中关闭此列表中的套接字。

于 2012-05-16T03:12:58.193 回答
1

对于那些可能最终在谷歌上搜索相同错误消息的人。我的代码中的问题是,当旧会话未正确关闭时创建新会话(snmp_close 可能失败,我没有检查此问题)可能会在新会话上引发此错误。

我通过使用 snmp_close_sessions() 解决了这个问题。

于 2017-12-29T17:56:41.860 回答