возвращаемые системным вызовом значения и 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)


Псевдопеременная 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

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