2011-05-08 42 views
7

私は、次のコードをデバッグしています:man 3 siginterruptアラームで説明したようにのrecvfrom()のタイムアウト()

signal(SIGALRM, testt);             
alarm(1);                 
result = recvfrom(listening_socket, buf, maxlen, 0, &from, &fromlen); 
printf("stoped\n");   

をシステムコールを中断しますが、私の場合にはそうではないはずです。アラームハンドラが呼び出されますが、recvfromは中断されません。

ただし、signal(2)関数で新しいシグナルハンドラを指定すると、システムコールはデフォルトで中断されます。

アラームハンドラの設定後にsiginterrupt(SIGALRM, 1);を追加すると、recvfromが期待どおりに中断されます。

私には何が欠けていますか?私のコードに何が問題なのですか?

注:signalsigactionに置き換えることは、私が探しているものではありません。

+0

'siginterrupt(3)'はPOSIX.1-2008では廃止とマークされていることに注意してください。 – ninjalj

答えて

9

siginterrupt(3)マンページが間違っています(Linuxマンページセットのversion 3.33がエラーを修正しています)。 glibcのsignalのデフォルトの動作は、ではなく割り込みシステムコールである信号を確立することです。あなたはstraceを自分のためにこれを見ることができます:

void handler(int unused) {} 
int main(void) 
{ 
    signal(SIGALRM, handler); 
} 

&longrightarrow。

$ strace -e trace=rt_sigaction ./a.out 
rt_sigaction(SIGALRM, 
      {0x4005b4, [ALRM], SA_RESTORER|SA_RESTART, 0x7fe732d3d490}, 
      {SIG_DFL, [], 0}, 8) = 0 

そこにはSA_RESTARTがあります。あなたは何をやっているのか、ハンドラーを確立した後にsiginterrupt(SIGALRM, 1)に電話をかけるか、またはsigactionに切り替えることができます。これにより、最初に好きなようにフラグを設定できます。あなたはそれをしたくないと言ったのですが(それはなぜですか?)、それでも私がお勧めするものです。

+0

TIL strace -e trace = rt_sigaction。ハンドラを設定するのは自分のコードではありません。 – Alexandru

+1

@Zack:マンページが間違っていない、誤って引用されています。完全な引用符は次のとおりです: 'flag引数がfalse(0)の場合、システムコールは指定されたシグナルsigによって中断された場合に再起動されます。これはLinuxのデフォルト動作です。しかし、signal(2)関数で新しいシグナルハンドラを指定すると、システムコールはデフォルトで中断されます。 ' – ninjalj

+0

@ninjalj:私はあまりにも疲れていると思います。なぜ最初の文が 'signal()' ? – Alexandru

関連する問題