編集可能

closeがEINTRを返したらどうするべきか

カーネルハッカーたちがcloseの仕様について辻斬りでバッサリするスレッド
プログラミング Linux NetBSD kernel
46
中村 実 @nminoru_jp
世の中には二通りの人間がいる。close()の復帰値を確認する人間としない人間だ。
KOSAKI Motohiro @kosaki55tea
@nminoru_jp 確認したところでたいていは手遅れで復旧不可能だけどね
中村 実 @nminoru_jp
@kosaki55tea どうなんでしょう。close()がEINTRで返ってきた場合にリトライをかけないとリークが発生することがあります。FUSEでできた変なネットワークファイルシステムを使っている場合なんて特に。
鯉江 @koie
@nminoru_jp closeがエラーになったら異常系に飛ばしてました。EINTRリトライは考えてなかったっす。異常系処理でcloseするときもEINTRリトライはしないといけないなぁ。やばいなぁ。
Tanaka Akira @tanaka_akr
@nminoru_jp @kosaki55tea close(fd) が失敗した時に fd が生きていることがあるのですか。以前 NFS の quota でテストして close が失敗したときには fd は死んでいたので、close が失敗したらどうしようもないと思ってました。
KOSAKI Motohiro @kosaki55tea
@tanaka_akr @nminoru_jp Linux限定だと 1) fd table のクリア 2) f_op->flush() という順でエラーが起きる可能性があるのは2だけ、かつVFSのflushはNFSぐらいしか使ってないので、EINTR無視でいいはずです
KOSAKI Motohiro @kosaki55tea
@tanaka_akr @nminoru_jp 他のOSはしらないけど、EINTRでfdがクリアされてるかどうか不定のOSがあったらバグだと思う。しかしPOSIX的にはEINTR返ってきたらfildesの状態は unspecified なのだな。腐ってやがる・・・・
KOSAKI Motohiro @kosaki55tea
@tanaka_akr @nminoru_jp なので、ものすごく保守的に考えるとEINTRではリトライ、すでに閉じ済みだったら次はEBADFが帰ってくるはず。という仮定をすることになる・・・・のかなあ?めんどくさくてやってられないが
Tanaka Akira @tanaka_akr
fd の確保・解放と、資源との接続・切断が分離されていないのは Unix の design error だと思う。
Tanaka Akira @tanaka_akr
@kosaki55tea @nminoru_jp EBADF を期待しちゃうと signal handler で fd が allocate される可能性が。
KOSAKI Motohiro @kosaki55tea
@tanaka_akr @nminoru_jp ああ、ほんとですね。やっぱり規格のミスだよなあ。これ
成瀬 @nalsh
@nminoru_jp @kosaki55tea 下手にリトライかけると新しく割り当てられた他人のfdを解放してしまう恐れがあるので、その変なネットワークファイルシステムの方がおかしいように思います
KOSAKI Motohiro @kosaki55tea
@nalsh @nminoru_jp Linuxの場合closeが返ってきた時はfdが無効化されてるが保証されてるのでリトライは100%意味がなく、たとえFSがバグっていたと仮定してもリトライは変な気がします。あとNFSもEINTR返すからEINTR自体はバグではない
KOSAKI Motohiro @kosaki55tea
@nalsh @nminoru_jp むしろNFSもEINTR返すなよって気はするけどな。わたしは
Tanaka Akira @tanaka_akr
そういえば、socket も linger で close 時の error があったような...
成瀬 @nalsh
@kosaki55tea @nminoru_jp ちなみにFreeBSDもfd無効化保証していますね
成瀬 @nalsh
@tanaka_akr FreeBSDはECONNRESETを返すことがありますな
SODA Noriyuki @n_soda
@nalsh @kosaki55tea @nminoru_jp http://t.co/UIcazQ3wUV みると、だいたいどのOSも、EINTR返した時には既にfd無効化済みみたいですね(Solarisもそうみたい)。リトライが必要なのはHP-UXっぽい。
KOSAKI Motohiro @kosaki55tea
@tanaka_akr 今手元にあるソースだとlingerのときの処理は返り値無視してるのでerrorはユーザ空間まで伝搬しないように見えるけどなあ
SODA Noriyuki @n_soda
@nalsh @kosaki55tea @nminoru_jp あとAIXはmanにfdが無効化されてると明記されてるとありますね。HP-UXは逆にリトライが必要と明記されているという。Solaris 9のmanにはunspecifiedとありますが実際には無効化済みなのかしら
Tanaka Akira @tanaka_akr
@kosaki55tea 体験したわけじゃなくて、本で読んだ記憶があるという話です。Stevens だった気がする。
SODA Noriyuki @n_soda
@koie リトライすると、かえって @nalsh さんが書いてた race condition によるバグが増えるので、リトライするなら #ifdef hpux が必要ってことなんじゃないでしょうか。
成瀬 @nalsh
@n_soda @koie closeのrace conditionはデバッグ大変なので安易にリトライすると大変ですよ……
鯉江 @koie
@n_soda 見落としてました。ちゃんとmanpageにかいてありますねEINTR以外はdeallocated。じゃぁcloseするまえにfsyncするのは必須ってことですかね、ファイルシステムのばあいは。ソケットだと上のレイヤ―で確認したほうが簡単かなぁ。
SODA Noriyuki @n_soda
@nalsh @koie 発生したら関係ないファイルに間違えて書くとかありうるので、デバッグ大変だけじゃなく、データ失うとかいうヤバいバグに…
残りを読む(38)

コメント

狐謡 @Towa_towa_to 2013年10月30日
なにこのルー大柴の集団w
KOSAKI Motohiro @kosaki55tea 2013年10月31日
. @Hiroki_Sato 先生のSUSの規格ステータスの見方に関するコメントを追加しました
藤枝和宏 - ぱんなこった@佐鎮 @kfujieda 2013年10月31日
Towa_towa_to ルー大柴の集団とは斬新な見方だなあ。
KOSAKI Motohiro @kosaki55tea 2013年10月31日
むしろルー大柴の集団っておもしろすぎるので布教したい。
Takanori Watanabe @takawata19 2013年10月31日
ファイルをcloseするとEINTRがreturn valueになることがあるのデース。
KOSAKI Motohiro @kosaki55tea 2013年10月31日
イーインタがリターンヴァリュでクローズなのデース。 #ルー大柴集団
藤枝和宏 - ぱんなこった@佐鎮 @kfujieda 2013年10月31日
ギークがルー大柴をイミテイトすると金剛になってしまうのデース!
Tsuyoshi CHO @tsuyoshi_cho 2013年10月31日
クライアントアプリ(すぐ終了)ならプロセス終了にまかせてもいい...?ただ、システムの構造に密接なサービスとかでないなら、特定のOS、ファイルシステム(の実装)に依存しないほうがいいと思うけど。どのシステムでもFSの実装なんて変ってしまう可能性はあるんだし。
SODA Noriyuki @n_soda 2013年11月1日
tsuyoshi_cho EINTRを返した場合の対処に「特定のOSに依存しない方法」は存在しないです( HP-UXの仕様が他と異なるため)。あとfdを無効化するか否かはFSより上のレイヤで実装されてるので、OS同じならFSには依存しないかと。
SODA Noriyuki @n_soda 2013年11月1日
tsuyoshi_cho なお、すぐプロセス終了ならOSに依存しません。いずれにせよ、書き込みが成功しているか否かはclose(2)以外の手段で調べるべきですし。あと、ローカルファイルシステムならEINTRがそもそも返りません。
Tsuyoshi CHO @tsuyoshi_cho 2013年11月2日
n_soda なるほど...了解です。まあそれでも、特定の実装(どのレイヤだって改良で変化しうるし)には依存しないようにしたいなー
ログインして広告を非表示にする
ログインして広告を非表示にする