Утечка дескриптора файла приводит к потоку сообщений об ошибках от net-snmp. Звучит знакомо?


Я столкнулся со странной проблемой, когда огромное количество сообщений от snmp_synch_response () snmplib умудряются заполнить жесткий диск объемом 60 ГБ примерно за три часа. часы. Сообщения все "Используйте snmp_sess_select_info2() для обработки большие файловые дескрипторы", иногда повторяемые более ста раз в секунду. линия. Я все еще работаю с клиентом, чтобы выяснить, как воспроизвести это в доме, но я подумал, что спрошу здесь на случай, если это старый вопрос или, по крайней мере, по крайней мере, видел кто-то другой. в каком-то смысле.

Вот основная информация о системе: 8.1-RELEASE-p2 FreeBSD i386. Сеть-SNMP версия 5.5.

Ниже приведен упрощенный фрагмент ключевых частей моего кода. Код сначала составляется список задач с инициализированными, но не открытыми сеансами. В другом месте каждая задача, вплоть до небольшого предела (64 в данном случае), раздваивается и дети открывают сокеты сеанса SNMP с помощью snmp_open(), и так далее. на. Я прочесал каждый из 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);
}
2 2

2 ответа:

В случае, если кому-то удастся столкнуться с чем-то подобным, это (неудивительно) закончилось тем, что не имело ничего общего с net-snmp. Каждый дочерний процесс связывается с родительским через свой собственный сокет. По основной природе fork(), Родительский список сокетов копировался каждому дочернему; решение состояло в том, чтобы просто закрыть сокеты в этом списке в дочернем коде.

Для тех, кто может закончить здесь гуглить то же самое сообщение об ошибке. Проблема в моем коде заключалась в том, что создание новых сеансов, когда старые не закрыты должным образом (snmp_close может завершиться ошибкой, я не проверял это), может вызвать эту ошибку в новых сеансах.

Я решил эту проблему с помощью snmp_close_sessions().