3

プログラムで次のシステムコールを使用しています。

recvfrom
sendto
sendmsg

そして、上記の各システムコールから、中断することなく完了するかどうかを確認し、中断された場合は再試行します。

元:

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の場合も同じです。

サーバークライアントのセットアップにアクセスできないため、これを実際に確認することはできません。何か案が?

ありがとう

4

2 に答える 2

7

recvfrom-1中断された場合(およびに設定errnoされた場合)に戻りますEINTR。したがって、次のことを確認する必要がありますlen

if(len == -1) {
    if(errno == EINTR) {
        syslog(LOG_NOTICE, "recvfrom interrupted");
        goto recvagain;
    } else {
        /* some other error occurred... */
    }
}
于 2012-10-17T04:44:22.833 に答える
4

errno疑似「変数」は、成功したシステムコールでは変更されない場合があります。したがって、その値をテストする前recvfrom、またはテストしたときにクリアすることができます。len<0

詳細については、errno(3)のマニュアルページを参照してください。

実際、Robert Xiao(nneonneo)がコメントしerrnoたように、システムコールが失敗したときにそれを記述してテストするべきではありません(その場合、C関数-たとえば、recvfrom-そのsyscallをラップしてerrno-1を返す前に記述します)。

于 2012-10-17T04:54:47.740 に答える