2009-11-04 25 views
5

私のユーザスペースアプリケーションは、何らかの理由でEINTR-Signalを受信した後でブロックされることがあります。私はstraceので記録何EINTR(中断されたシステムコール)を処理する方法

time(NULL)        = 1257343042 
time(NULL)        = 1257343042 
rt_sigreturn(0xbff07be4)    = -1 EINTR (Interrupted system call) 
--- SIGALRM (Alarm clock) @ 0 (0) --- 
time(NULL)        = 1257343042 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGUSR1 (User defined signal 1) @ 0 (0) --- 
sigreturn()        = ? (mask now [ALRM]) 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGWINCH (Window changed) @ 0 (0) --- 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGTERM (Terminated) @ 0 (0) --- 
time(NULL)        = 1257343443 
time(NULL)        = 1257343443 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted) 
--- SIGWINCH (Window changed) @ 0 (0) --- 
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2 

私はEINTRシグナルをキャッチすることができますし、どのように私は、このような書き込み、読み出しや選択などの懸念のコールを繰り返すことができますか?システムコールで動作するサードパーティのライブラリを使用したとしても、このEINTRがどこで発生したのかをどのように判断できますか?

なぜ私のアプリはEINTRを受け取った後に完全にブロックされますか(straceのダンプを参照してください:通常は処理すべきSIGUSR1を送信しました)?そして、futex()がERESTARTSYSをユーザー空間に戻すのはなぜですか?

おかげ

+3

で「敗者モード」の説明を参照してください。 –

+0

'gstack'または' gdb'を使用してスタックトレースを取得し、プログラムが現在スタックしている場所を見つけます。 – mark4o

答えて

17

書き込み(または他のブロッキング操作)を呼び出すコードはEINTRを認識しなければなりません。ブロッキング操作中にシグナルが発生すると、操作は(a)部分的な完了を返すか、(b)リターンの失敗を返し、何もしないで、errnoをEINTRに設定します。

while(size > 0) { 
    int written = write(filedes, buf, size); 
    if (written == -1) { 
     if (errno == EINTR) continue; 
     return -1; 
    } 
    buf += written; 
    size -= written; 
} 
return 0; // success 

またはEINTRを再試行行儀少し良く何か、について

は、できるだけ多くの書き込み:中断後に再試行し、書き込み動作を全か失敗のために

そう、あなたはこのような何かをしたいです

int total = 0; 
while(size > 0) { 
    int written = write(filedes, buf, size); 
    if (written == -1) { 
     if (errno == EINTR) continue; 
     return (total == 0) ? -1 : total; 
    } 
    buf += written; 
    total += written; 
    size -= written; 
} 
return total; // bytes written 

GNU非標準を持っている:それができる、との報告が失敗に書かれているどのくらいの(その呼び出し側が信号による割り込み以外の理由で失敗し、部分的な書き込みを継続するかどうか、どのように決めることができる)など関心のあるかもしれないTEMP_FAILURE_RETRYマクロですが、私は私がそれらを必要とするときにそれのためのドキュメントを見つけることは決してできません。今を含む。

+1

ありがとう、私はhttp://www.gnu.org/s/libc/manual/html_node/Interrupted-Primitives.htmlのマクロにDocuを見つけました ロックされたfutex()関数について知っていますか? – Maus

+1

ERESTARTSYSについて知りません。私はそれが内部実装の詳細だと思います。あなたはそれをトレースで見ることができますが、ユーザ・モードのシステム・コードは返されたコールを再試行するか、EINTRに変換する必要があるため、 。しかし、私は間違っているかもしれません。私は最後に土曜日に剃ったので、完全なLinuxのgeek資格情報のようなものはありません;-) –

+2

futexはセマフォのような高レベルのものを構築するためのLinux固有の "軽待ち"ミューテックス。 futex(7)を参照してください。 –

2

はEINTRが、信号ではなく、エラー番号がシグナルによって割り込まれたシステムコール時に返されるも Worse is Better

関連する問題