getaddrinfo () возвращает 0 (успех), но устанавливает errno в EINVAL (22) - PullRequest
0 голосов
/ 18 февраля 2020

У меня проблемы со следующим фрагментом кода:

#include <errno.h>
#include <stdlib.h>

#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>


[...]
    struct protoent *tcp;
    struct addrinfo hint = {0};
    struct addrinfo *addrs;
    int             status;

    tcp = getprotobyname("tcp");
    if (!tcp)
        return  -EINVAL;
    hint.ai_family      = AF_UNSPEC;
    hint.ai_socktype    = SOCK_STREAM;
    hint.ai_protocol    = tcp->p_proto;
// errno is 0
    status  = getaddrinfo("localhost", "30002", &hint, &addrs);
// errno is 22
    if (status)
        return  -labs(status);
[...]

Проблема в том, что, хотя это работает (я использую это для связи TCP, которая действительно работает), это противоречиво:

man getaddrinfo ничего не говорит о errno; вместо этого он возвращает код ошибки. Почему это может быть внутренняя установка errno в EINVAL (22, неверный аргумент)?

1 Ответ

7 голосов
/ 18 февраля 2020

Неважно, почему это происходит. errno имеет значение только для вас, когда в вашем коде произошел сбой вызова функции, и эта функция предназначена для использования errno для сообщения вам об ошибках. Но это не относится к getaddrinfo() в большинстве ситуаций.

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

Так что, пока getaddrinfo() сам не является сообщив вам код ошибки, вы просто не можете полагаться на errno, имеющую любое значащее значение. errno изменение значения - это просто побочный эффект внутренней реализации getaddrinfo() в вашей системе.

ЕДИНСТВЕННЫЙ раз, когда вы должны смотреть на errno после выхода getaddrinfo() когда getaddrinfo() возвращает EAI_SYSTEM, ТОЛЬКО ТОГДА errno будет иметь для вас значимое значение.

...