3

これは私のサーバー側コード (の一部) です

void timeout_handler(int value) {
    printf("Handler\n");
    return;
}

int main (int argc, char **argv) {
    [...]
    signal(SIGALRM, timeout_handler);
    alarm(seconds);
    int result = read(input_socket, buffer, sizeof(buffer));
    if (result == -1 && errno == EINTR) {
        printf("read() failed\n");
    }
    [...]
}

ここinput_socketで、クライアントに正しく接続された TCP ソケットです (クライアントからデータを送信すると、サーバーがデータを受信します)。

アラーム信号のテストとして、データを送信せずにクライアント側でソケットを開いて接続しようとしました。次のような出力が期待されます

Handler
read() failed

ただし、結果はHandlerメッセージのみであり、プロセスはまだアクティブです。

read()で失敗しないのはなぜerrno=EINTRですか?

4

1 に答える 1

1

また、OSXでは、シグナルによって中断された場合、特定のシステム コールがデフォルトで再起動されます。

siginterrupt()この動作を変更するために使用できます。次の行(呼び出される前のどこかalarm())は、プログラムがOPによって期待どおりに動作するようにするために仕事をする必要があります。

siginterrupt(SIGALRM, 1);

OSXのドキュメントから(私が強調):

一部のシステム コールでは、コールの実行中にシグナルが捕捉され、コールが途中で終了した場合、コールは自動的に再開されます。 signal(3) を使用してインストールされたハンドラには SA_RESTART フラグが設定されます。これは、再起動可能なシステム コールがシグナルを受信して​​も返されないことを意味します。影響を受けるシステム コールには、通信チャネルまたは低速デバイス上で、ioctl(2 ) ) または待機 (2)。ただし、既にコミットされている呼び出しは再開されませんが、代わりに部分的な成功 (短い読み取りカウントなど) が返されます。これらのセマンティクスは、siginterrupt(3) で変更できます。

これは、たとえば、中断された可能性のあるシステム コールの再起動を、送信されたシグナルによって明示的に要求する必要がある Linux では異なります。

于 2013-08-31T14:09:57.223 に答える