Sendmsg выходит из строя с кодом ошибки 3 (ESRCH)

ОС: Linux 2.6.24 (x86)

Мое приложение работает на сервере, на котором несколько клиентов подключаются к нему по UDP-порту 4500.
С перерывами приложение не может отправить UDP-трафик клиентам на UDP-порт 4500

Это происходит из-за сбоя системного вызова sendmsg с кодом ошибки 3 (ESRCH)
man page для sendmsg не говорит об ошибке ESRCH

Проблема не устраняется даже после убийства приложения и его повторного запуска.
UDP-трафик на других портах, работающих нормально

Перезагрузка сервера - единственное решение.

С ядром 2.6.11 я не видел таких проблем.

Любая идея о том, как отладить эту проблему?

Ответы

Ответ 1

Чтобы отладить эту проблему, учитывая имеющуюся информацию, я думаю, что лучшим стартовым местом является просмотр способа возврата sendmsg ESRCH. Сначала нам нужно получить исходный код для конкретной версии ядра, с которой вы столкнулись, я нашел здесь

После некоторого рытья мы можем видеть, что следующая цепочка может выполняться:

net/ipv4/udp.c:646:     
    err = ip_route_output_flow(&rt, &fl, sk, 1);

net/ipv4/route.c:2421:
    err = __xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);

net/xfrm/xfrm_policy.c:1380:
    pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN,
                            fl, family,
                            XFRM_POLICY_OUT);

net/xfrm/xfrm_policy.c:890:
    err = xfrm_policy_match(pol, fl, type, family, dir);

Наконец, мы заканчиваем на net/xfrm/xfrm_policy.c:854:xrfm_policy_match

/*
 * Find policy to apply to this flow.
 *
 * Returns 0 if policy found, else an -errno.
 */
static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
             u8 type, u16 family, int dir)
{
    struct xfrm_selector *sel = &pol->selector;
    int match, ret = -ESRCH;

    if (pol->family != family ||
        pol->type != type)
        return ret;

    match = xfrm_selector_match(sel, fl, family);
    if (match)
        ret = security_xfrm_policy_lookup(pol, fl->secid, dir);

    return ret;
}

Итак, похоже, что ошибка исходит от xfrm_policy_match, если вы проверяете код в xfrm_lookup_bytype, вы найдете цикл, который продолжается до тех пор, пока итератор не будет исчерпан, или возвращаемое значение xrfm_policy_match не ESRCH.

Это говорит о том, что ваши вызовы sendmsg терпят неудачу, потому что для вашего порта нет политики xfrm. Когда вы заявляете, что он работает, ошибка возникает и сохраняется, это говорит о том, что политики xfrm в вашей системе настраиваются или повреждаются.

От взгляда на страницу руководства xfrm здесь мы видим, что есть некоторые инструменты для исследования политик. От чтения man-страницы мой следующий шаг будет выполняться ip xfrm state list, если проблема не произошла и после того, как она произошла, и сравните вывод. К сожалению, у меня нет работающей системы с ядром 2.6.24, чтобы копать все глубже.

Обратите внимание, что у меня нет никаких трюков, чтобы прийти к такому выводу, это было определено путем проверки кода, поиска и поиска. Это может занять много времени и усилий, особенно если вы не знакомы с базой кода. Чтобы исправить проблему, а не отлаживать ее, я бы попытался использовать разные версии ядра, прежде чем копать эту глубину.


TL; DR

Похоже, что ошибка ESRCH возникает из сетевой подсистемы под названием xfrm, существует набор инструментов для исследования xfrm, который можно найти на его странице руководства здесь

Похоже, что ошибка связана с отсутствующей политикой для адреса/порта, который вы пытаетесь отправить. Это может быть связано с изменением конфигурации во время работы системы или ошибкой, вызывающей повреждение политик xfrm.

Ответ 2

Я только что получил эту ошибку в OSX, когда хост в моей локальной сети был недоступен (ethernet отключен). Таким образом, похоже, что это может быть вызвано множеством условий. Возможно, маршрутизатор (аэропорт) создал ICMP.