人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Linux で、write(2) や close(2) を呼んだらエラー EINTR が発生した場合、ユーザプログラム側ではどう対処するのが正解ですか?

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/

●質問者: sardine
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● monyo
●300ポイント ベストアンサー

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.

と書いているので、問題は認識しているようですね。


sardineさんのコメント
write(2) の方はリトライで OK、close(2) はリトライすべきではないが……ということですね。 教えて頂いたリンク先も大変参考になりました。迅速かつ素晴らしい回答、ありがとうございます!

sardineさんのコメント
LKML の回答をたどってみたところ、「慎重にやりたい場合は fsync(2)」的なことが書いてあったので、まずは fsync(2) を呼ぶようにしてみます。 回答・コメントを頂いた皆さん、ありがとうございました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ