2016-06-18 3 views
1

を使用して、タイムアウトをrecvfromに設定します。しかし、signal()を使用してSIGALRMのハンドラを登録すると、SIGALRMが取得され、その後シグナルハンドラが呼び出されることが判明しました。しかし、ハンドラから返された後には、recvfrom()はまだブロックしている間にデータが来ず、EINTRエラーがありません。どうして? signal()は自動的にSA_RESTARTフラグを設定していますか?ここ はコードです:ブロッキング・コールが再起動されているかどうかSIGALRMがキャプチャされたときにrecvfrom()がまだブロックされていますか?

signal(SIGALRM, sig_handler); 
while(1) 
{ 
    alarm(5); 
    n = recvfrom(sock, buf, BUF_MAX, 0, (struct sockaddr*)&addr, &len); 
    if(n < 0) 
    { 
     if(errno == EINTR) 
     { 
      printf("recvfrom timeout\n"); 
      continue; 
     } 
     else 
     { 
      printf("recvfrom error\n"); 
     } 
    } 
    else 
    { 
     printf("data: %s\n", buf); 
     alarm(0); 
    } 
} 

void sig_handler(int signo) 
{ 
    return; 
} 
+0

実際の質問は、なぜSO_RCVTIMEOを使用していないのですか? – EJP

答えて

1

signalのmanページによると、プラットフォームに依存属性です:

次のようにLinux上の状況は次のとおりです。

  • カーネルのsignal()システムコールは、System Vのセマンティクスを提供します。
  • デフォルトでは、glibc 2以降では、signal()ラッパー関数はカーネルシステムコールを呼び出しません。代わりに、BSD セマンティクスを提供するフラグを使用してsigaction(2)を呼び出します。このデフォルトの動作は、適切な機能テストマクロが定義されている限り提供されます。glibc 2.19以前の_BSD_SOURCEまたは glibc 2.19以降の_DEFAULT_SOURCEです。このような機能テストマクロが定義されていない場合、signal() はSystem Vのセマンティクスを提供します(詳細については、feature_test_macros(7)を参照してください)。

BSDのセマンティクスは、以下のフラグでsigaction(2)を呼び出すのと同じですので:

sa.sa_flags = SA_RESTART; 

とSystem VセマンティクスがSA_RESTARTをしない、何を見たことは、あなたのプログラムは、BSDの道をやっているということですプログラムの定義済みの機能を得るには、前述の機能テストマクロを必ず使用するようにしてください。

関連する問題