Обработка EINTR (с goto?)
Предыстория: это дополнительный вопрос к этой теме об обработке EINTR для системных вызовов в C++ (Linux/GCC). Независимо от того, намереваюсь ли я профилировать свое приложение, мне кажется, что я должен обрабатывать настройки системных вызовов errno
в EINTR
как особый случай. Существует множество мнений об использовании goto
,
Мой вопрос: это настройка системных вызовов errno
в EINTR
случай, когда goto
считается номинальным? Если нет, то как бы вы предложили преобразовать следующий код для обработки EINTR
?
if ( ( sock_fd = ::socket( domain, type, protocol ) ) < 0 ) {
throw SocketException( "Socket::Socket() -> ::socket()", errno );
}
Заранее спасибо!
Ура,
-Крис
ОБНОВЛЕНИЕ: Основываясь на ответах ниже, я закончил писать следующий макрос:
#define SOCK_SYSCALL_TRY(call,error) \
while ( (call) < 0 ) { \
switch ( errno ) { \
case EINTR: \
continue; \
default: \
throw SocketException( (error), errno ); \
} \
} \
Который используется для преобразования моего исходного фрагмента в этот пример:
SOCK_SYSCALL_TRY( sock_fd = ::socket( domain, type, protocol ), "Socket::Socket() -> ::socket()" )
Надеюсь, это поможет кому-то еще!
2 ответа
Насколько я знаю, системный вызов сокета не может вернуться с errno, установленным в EINTR. Для других случаев я использую цикл:
while ((::connect(sock, (struct sockaddr *)&destAddress, sizeof(struct sockaddr))) == -1) {
if (errno == EINTR) {
LOGERROR("connect interrupted, retry");
continue;
} else if (errno == EINPROGRESS) {
break;
} else {
LOGERROR("connect failed, errno: " << errno);
return -1;
}
}
Я запрограммировал FTP-сервер, и мне никогда не приходилось использовать goto. Я обычно создавал прерывистые системные вызовы так:
while( (ret =
splice_stream( data, NULL, file, &block_offset,
XFER_BLOCK_SIZE )) == -1 )
{
switch( errno )
{
case EINTR:
if( server_handle_signal() )
return FTP_QUIT;
else
continue;
break;
case EPIPE:
case ECONNRESET:
return FTP_ABOR;
default:
log_fatal("Splice error: %m\n");
return FTP_ERROR;
}
}
EINTR означает, что ваш сервер получил сигнал, и большую часть времени важно обрабатывать этот сигнал.