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

カーネルハッカーたちがcloseの仕様について辻斬りでバッサリするスレッド
47
SODA Noriyuki @n_soda

@koie アプリケーション層のプロトコルで結果を確認することにして、close()の結果は気にしないってのが実用的な気がします。>たいてのプロトコル

2013-10-30 12:26:11
鯉江 @koie

@nalsh 基本はEINTRだけリトライすればよくてEBADFはバグなのであきらめて、ってことになるでしょうか。hpuxはしらんです。たぶんもう触ることはなさそうだし。

2013-10-30 12:27:02
SODA Noriyuki @n_soda

@koie @nalsh いや、EINTRでリトライする必要があるのはHP-UXだけで、他のOSでは、そもそもリトライしちゃだめ(ディスクリプタが無効化されてるし、multithreadプログラムだとraceがあるし)ってことなのでは?

2013-10-30 12:28:54
鯉江 @koie

そういえば、ファイルサーバのプロセスをデーモン化するときにfdをcloseしまくってたら、プログラム中にfprintf(stderr,...)でログを吐くコードがあってfd=2がディスクデバイスになっててファイルが静かに壊れていったという話を聞いた。

2013-10-30 12:29:54
成瀬 @nalsh

@n_soda @koie EINTRも多くのOSではリトライしちゃダメですね

2013-10-30 12:30:32
鯉江 @koie

@n_soda あ、さっきmanよんだところなのにもう忘れてた。やばい。でEINTRになったらファイルはどういう状態になってるんでしょうか?

2013-10-30 12:31:14
SODA Noriyuki @n_soda

@nalsh @koie たぶんHP-UXだけですよね>close(2)がEINTR返したときにリトライする必要があるOS。他にあるのかしら?

2013-10-30 12:32:10
小崎 資広 @kosaki55tea

@koie @n_soda HP-UX以外では、まだ書き込み終わってないけど、fd table的にはクリアしちゃったよん、という意味。これを聞いてリトライできないじゃん困るというアプリはfsync使えボケ攻撃が待っている

2013-10-30 12:32:58
SODA Noriyuki @n_soda

@koie close(2)がEINTRを返した時にディスクリプタが無効化されるOSでは、カーネルがあとで勝手に処理をリトライしてくれて、資源も解放されると思います。されなかったらカーネルのバグ扱いでしょう。

2013-10-30 12:33:49
鯉江 @koie

fsync(2)にはEINTRがないな。

2013-10-30 12:35:08
小崎 資広 @kosaki55tea

@n_soda @koie いやリトライなんかされてねーと思いますよ。そださんがさっき出してくれたリンク見るとそんな感じのこと書いてある

2013-10-30 12:35:26
SODA Noriyuki @n_soda

@koie POSIXにはEINTRも載ってますよ: http://t.co/QAdGs6mHYx マニュアルで抜けてる理由は、ブロックデバイスはEINTR返さないせいのような。でもintrないしsoftマウントしているNFS先にfsync(2)したらEINTRが返るかと。

2013-10-30 12:37:35
ふみやす@シェルまおう(自称でない) FGO:838,149,789 @satoh_fumiyasu

HP-UX 以外(?)では close(2) は fd が無効になることを保証しているらしいけど、なんで EINTR の場合もそうなのかは不思議でならない。close 処理は完了していないけど、fd は無効な状態ってことかな? https://t.co/TsItWqDmh6

2013-10-30 12:37:48
小崎 資広 @kosaki55tea

@satoh_fumiyasu そのとおり。個人的にはよくない仕様だなあと思ってます

2013-10-30 12:38:20
小崎 資広 @kosaki55tea

しかしそださんの博学はいつ聞いてもおそろしいなあ。

2013-10-30 12:40:22
小崎 資広 @kosaki55tea

しかし posix_close()とか、出来ても絶対だれも使わないと思う。さすがに手遅れだと思うし、対処も場当たり的すぎる

2013-10-30 12:41:47
SODA Noriyuki @n_soda

@kosaki55tea (あ、ちゃんと読んでないのがバレた) リトライするかどうかは、クローズが実際に起こす動作によるような。NFSの場合、カーネル内のダーティなバッファを解放する必要があるので、最終的にリトライが起きるんじゃないでしょうか?←コード読んでないです

2013-10-30 12:43:42
中村 実 @nminoru_jp

@kosaki55tea @tanaka_akr なるほどLinuxのclose(fd)でEINTRでリトライは無駄というか有害ですか。

2013-10-30 12:45:22
SODA Noriyuki @n_soda

@kosaki55tea HP-UXが滅ぶ→OpenGroupが現状追認 という結果になりそうな。もしItaniumが続くならHP-UXも存続するでしょうけど、その可能性って…

2013-10-30 12:45:39
小崎 資広 @kosaki55tea

@n_soda 必要? closeでflushするのはただの習慣であって必須ではありませんよ。HAHAHA。という確信犯にしか見えないのですが

2013-10-30 12:45:47
SODA Noriyuki @n_soda

@kosaki55tea NetBSDの場合、close(2)でflushしているのはNFSv3の場合だけで、v2の場合は、その後のバッファ管理に任せてますね。(実はそこだけは読んでから書いたのです^^;)

2013-10-30 12:47:30
中村 実 @nminoru_jp

@n_soda @koie Linuxだとクラウドストレージだの分散ファイルシステム用のFUSEでできたファイルシステムが大量にありますが、エラー処理が甘いのが多いので…

2013-10-30 12:51:31
小崎 資広 @kosaki55tea

@n_soda Linuxの場合バージョンによらずfsyncしてるだけなので、プロトコル上何回も往復してる途中のどこかでEINTR返すとそれがそのままユーザー空間まで漏れますね。その場合はカーネルのflusher threadがflushしてくれるまでカーネルに滞留しそう

2013-10-30 12:52:01
鯉江 @koie

@nminoru_jp @n_soda じーふぁーむはどうなってるかきになるところ

2013-10-30 12:52:03
SODA Noriyuki @n_soda

@nminoru_jp @koie FUSEの場合も、close(2)がEINTRを返した時にはfdは無効化されてるでしょうから、対策としてはclose(2)のリトライではなく、fsync(2)しとくとか、ユーザーに通知するとか、open(2)からやり直すとかではないでしょうか。

2013-10-30 12:57:59