12

man signal(7)SA_RESTARTによると、シグナルハンドラをインストールするときにフラグが使用されている場合、一部のシステムコールはカーネルによって透過的に再起動できます。

次のインターフェイスのいずれかへのブロックされた呼び出しがシグナル ハンドラーによって中断された場合、SA_RESTART フラグが使用されていれば、シグナル ハンドラーが戻った後に呼び出しが自動的に再開されます。そうしないと、呼び出しはエラー EINTR で失敗します。

次に、再起動できる(およびできない)いくつかのシステムコールについて言及していますがclose()、どちらの場所でも言及していclose()ません。それを指定しPOSIXますか、それとも Linux 固有の動作ですか? 詳細はどこで確認できますか?

4

2 に答える 2

14

closeはかなり特殊なケースです。Linux で再起動できないだけではありません。Linux で withをclose返すとEINTR、実際には既に成功しており、別の呼び出しをclose行うと、シングルスレッド プロセスで with が失敗しEBADF、マルチスレッド プロセスで非常に危険なファイル記述子の競合が発生します。

公開された POSIX 2008 では、次の動作が許可されています。

close() がキャッチされるシグナルによって中断された場合、errno が [EINTR] に設定されて -1 が返され、fildes の状態は指定されません。

この問題は Austin Group で ( Issue #529EINTRとして) 提起され、ファイル記述子がまだ開いていることを意味する を返すように仕様を修正することで解決されました。これは、現在の Linux の動作に反します。シグナルが処理された時点でファイル記述子がすでに閉じられている場合、関数はではなくcloseを返す必要があります。これは Linux のユーザー空間で修正できます。また、オープンなglibc バグ レポート (#14627 ) がありますが、この記事を書いている時点ではまだ応答がありません。EINPROGRESSEINTR

この問題は、POSIX スレッド キャンセルにも深刻な影響を及ぼしますEINTR。Austin Group トラッカーに関連する問題、Issue #614があります。

于 2013-01-21T02:52:45.547 に答える
10

POSIX.1-2008に従って、SA_RESTARTフラグはすべての中断可能な関数に適用されます (すべての関数は で失敗すると文書化されていますEINTR):

SA_RESTART

このフラグは、割り込み可能な関数の動作に影響します。つまり、errno が [EINTR] に設定されて失敗するように指定されたものです。設定されていて、割り込み可能として指定された関数がこの信号によって中断された場合、関数は再起動し、特に指定されていない限り [EINTR] で失敗しません。タイムアウトを使用する割り込み可能な関数が再開される場合、再開後のタイムアウトの期間は、元のタイムアウト値を超えない不特定の値に設定されます。フラグが設定されていない場合、この信号によって中断された割り込み可能な機能は、errno が [EINTR] に設定されて失敗します。

つまり、再起動されない関数のリストは Linux 固有のものです (おそらくバグとしてカウントされます)。

于 2012-11-13T08:09:42.743 に答える