3

背景:これは、 C ++(Linux / GCC)でのシステムコールのEINTRの処理に関するこのスレッドのフォローアップ質問です。アプリケーションのプロファイルを作成するかどうかに関係なく、システムコールの設定errnoEINTR特別な場合として処理する必要があるようです。の使用については、多くの多くの多くのgoto意見があります。

私の質問:システムコールは、名目上のものと見なされる場合に設定errnoされていますか?そうでない場合は、次のコードを処理するように変換することをどのように提案しますか?EINTRgotoEINTR

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()" )

これが他の誰かに役立つことを願っています!

4

2 に答える 2

4

私の知る限り、ソケットシステムコールは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;
    }
}
于 2010-06-02T13:44:28.667 に答える
2

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は、サーバーがシグナルをキャッチしたことを意味し、ほとんどの場合、そのシグナルを処理することが重要です。

于 2010-06-02T13:46:28.413 に答える