возвращаемые системным вызовом значения и errno

Я использую следующие системные вызовы в своей программе:

recvfrom
sendto
sendmsg

И из каждого упомянутого выше системного вызова я проверяю, завершается ли он без прерывания, и в случае, если он прерван, я повторяю попытку.

Ex:

recvagain:
    len = recvfrom(fd, response, MSGSIZE, MSG_WAITALL, (struct sockaddr *)&from, &fromlen);
    if (errno == EINTR) {
           syslog(LOG_NOTICE, "recvfrom interrupted: %s", strerror(errno));
           goto recvagain;
    }

Проблема здесь в том, что мне нужно сбрасывать значение errno на 0 каждый раз, когда он терпит неудачу. Или, если recvfrom() успешно, сбрасывает ли errno значение 0?

Страница руководства recvfrom() говорит:

После успешного завершения recvfrom() возвращает длину сообщения в байтах. Если нет сообщений, доступных для приема, и одноранговый узел выполнил правильное завершение работы, recvfrom() возвращает 0. В противном случае функция возвращает -1 и устанавливает errno, чтобы указать на ошибку.

тот же случай с sendto и sendmsg.

Я не могу проверить это сейчас, так как у меня нет доступа к настройке сервер-клиент. Есть идеи?

Спасибо


person Ram    schedule 17.10.2012    source источник


Ответы (2)


arrow_upward
4
arrow_downward

Псевдопеременная errno может не изменяться при успешных системных вызовах. Так что вы могли очистить его либо до вашего recvfrom, либо когда len<0 и протестировав его значение.

См. errno(3) справочную страницу. для большего.

На самом деле, как прокомментировал Роберт Сяо (nneonneo), вы не должны писать errno и просто тестировать его, когда системный вызов не работает (в этом случае функция C, например, recvfrom и т. 1).

person Basile Starynkevitch    schedule 17.10.2012
comment
Вам редко нужно очищать errno; Я не думаю, что это один из тех случаев. - person nneonneo; 17.10.2012
comment
Основная причина очистки errno состоит в том, чтобы покрыть случай, когда он был ранее установлен (некоторое время назад) несвязанным системным вызовом. - person Basile Starynkevitch; 17.10.2012
comment
Обычно вам должно быть все равно. Как я указал в своем ответе, правильное решение - проверить len, чтобы увидеть, действительно ли произошла ошибка. - person nneonneo; 17.10.2012
comment
@BasileStarynkevitch Но обычно в этом нет необходимости, потому что вы должны всегда проверять возвращаемое значение прежде чем смотреть на errno. Это необходимо только при вызове функций, в которых значение, указывающее на состояние ошибки (например, -1 для getpriority(2) или NULL для readdir(3)) также является допустимым ответом функции (хорошее значение -1 или конец каталога). поток соответственно). - person Dato; 05.09.2017

arrow_upward
7
arrow_downward

recvfrom возвращает -1, если оно прерывается (и устанавливает errno в EINTR). Поэтому стоит просто проверить len:

if(len == -1) {
    if(errno == EINTR) {
        syslog(LOG_NOTICE, "recvfrom interrupted");
        goto recvagain;
    } else {
        /* some other error occurred... */
    }
}
person nneonneo    schedule 17.10.2012
comment
Хорошо, я сделаю это, а как насчет errno? Вы хотите сказать, что он не сбрасывается, если системный вызов успешен, я прав? - person Ram; 17.10.2012
comment
errno можно доверять только в том случае, если функция вернула значение, указывающее на ошибку. В противном случае это может быть бессмысленно. - person R.. GitHub STOP HELPING ICE; 17.10.2012