我遇到了一个奇怪的问题,来自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);
}
如果有人设法遇到类似的东西,这(不出所料)最终与net-snmp没有任何关系。每个子进程通过自己的套接字与父进程通信。根据fork()的基本特性,父节点的套接字列表被复制到每个子节点;解决方案只是关闭子代码中此列表中的套接字。
对于那些可能最终在谷歌搜索相同的错误消息。我的代码中的问题是,当旧的会话未正确关闭时创建新会话(snmp_close可能会失败,我没有检查这个)可能会在新会话上抛出此错误。
我通过使用snmp_close_sessions()解决了这个问题。