NFS のような「遅い」ファイルシステムをマウントしている場合、設定にもよりますが、ファイル I/O 系のシステムコールで EINTR が発生することがありますよね。
ネットで検索すると「EINTR が起きたら同じシステムコールをもう一度呼べ」と書いてあるページがいくつか見つかったのですが、write(2) を 2 回呼び出すと同じ内容を重複して書き込んでしまいそうです。
また、下記ページの投稿を見ると、close(2) を 2 回呼び出すと EBADF が起きる可能性があるとか、ファイルディスクリプタがすでに他のスレッドで再利用されている場合があるから危険だと書いてあって、どうすればいいのかわかりません……。
When the programmer is forced to handle return codes
http://lwn.net/Articles/365294/
write(2) については、たとえば WRITE に
何のデータも書かない間にシグナルにより割り込まれた (interrupt)。
Linux の write(2) の原文では
The call was interrupted by a signal before any data was written;
と書かれているとおりですので、同じ内容が何度も書かれてしまう懸念は仕様上はないはずです。
わたしも EINTR の場合は、基本的にリトライするようにコーディングしてました。
close(2) の EINTR 問題は、いままで認識したことがなく、興味深い(というか悩ましい)ですね。
Invoke close() again if it fails with EINTR? Think again. や、そこからたどれる Re:uml: retry host close() on EINTR でのリーナス自身のコメントをみていると、EINTR が出ても無視するしかないように見えます。
ただ、
I'm going to drop this patch, but in case you've ever seen a case where
EINTR actually means that the fd didn't get closed, please holler, and we
need to fix it.
と書いているので、問題は認識しているようですね。
write(2) の方はリトライで OK、close(2) はリトライすべきではないが……ということですね。
教えて頂いたリンク先も大変参考になりました。迅速かつ素晴らしい回答、ありがとうございます!
2011/10/25 01:04:02LKML の回答をたどってみたところ、「慎重にやりたい場合は fsync(2)」的なことが書いてあったので、まずは fsync(2) を呼ぶようにしてみます。
回答・コメントを頂いた皆さん、ありがとうございました。
2011/10/31 23:40:09