5

私のアプリケーションはlseek()、データを書き込むための目的の位置を探すために使用します。ファイルはを使用して正常に開かれ、open()私のアプリケーションは何度も使用できました。lseek()write()

ある時点で、一部のユーザーにとっては簡単に再現できない場合は、 lseek()-9で-1を返しますerrno。これより前にファイルが閉じられず、ファイルハンドル(int)がリセットされません。

この後、別のファイルが作成されます。open()再び大丈夫でありlseek()write()再び動作します。

さらに悪いことに、このユーザーは完全なシーケンスを再試行し、すべてが順調でした。

だから私の質問は、OSが何らかの理由でファイルハンドルを閉じることができるかということです。何が原因でしょうか?ある種のファイルインデクサーまたはファイルスキャナー?

これを解決するための最良の方法は何ですか。この擬似コードは最良の解決策ですか?(コードレイアウトを気にせず、そのための関数を作成します)

int fd=open(...);
if (fd>-1) {
  long result = lseek(fd,....);
  if (result == -1 && errno==9) {
      close(fd..); //make sure we try to close nicely
      fd=open(...);

      result = lseek(fd,....);
  }
}

誰かが似たようなことを経験しますか?

概要:ファイルのシークと書き込みは、特定のfdに対して正常に機能し、理由もなく突然errno=9を返します。

4

4 に答える 4

7

だから私の質問は、OSが何らかの理由でファイルハンドルを閉じることができるかということです。>これを引き起こす可能性があるのは何ですか?ある種のファイルインデクサーまたはファイルスキャナー?

いいえ、これは起こりません。

これを解決するための最良の方法は何ですか。この擬似コードは最良の解決策ですか?(コードレイアウトを気にせず、そのための関数を作成します)

いいえ、最善の方法はバグを見つけて修正することです。

誰かが似たようなことを経験しますか?

fdsが何度も台無しになり、一部のケースではEBADFが発生し、他のケースでは見事に爆発するのを見てきました。

  • バッファオーバーフロー-何かをオーバーフローさせ、意味のない値を「intfd;」に書き込みます。変数。
  • if(fd = foo[i].fd)誰かが意図したときに誰かがやったいくつかのコーナーケースのために起こる愚かなバグ if(fd == foo[i].fd)
  • スレッド間の競合状態。一部のスレッドは、他のスレッドが使用したい間違ったファイル記述子を閉じます。

この問題を再現する方法を見つけることができたら、「strace」の下でプログラムを実行して、何が起こっているかを確認してください。

于 2010-03-30T12:46:27.670 に答える
2

OSはファイルハンドルをランダムに閉じてはなりません(私はUnixライクなシステムを想定しています)。ファイルハンドルが閉じている場合は、コードに問題があります。おそらく他の場所に問題があります(C言語とUnix APIのおかげで、これはコード内のどこにでもある可能性があり、たとえば、わずかなバッファが原因である可能性があります。本当に無関係のように見えるコードの一部でオーバーフローします)。

疑似コードは、バグがまだ潜んでいる間に問題を修正したという印象を与えるため、最悪の解決策です。

printf()ファイルまたはソケットを開いたり閉じたりする場所にデバッグプリント(つまり呼び出し)を追加することをお勧めします。また、Valgrindを試してください。

(昨日、不気味な1つずつのバッファオーバーフローが発生しました。これにより、CPUレジスタを保存するためにコンパイラによって生成された一時スロットの最下位バイトが破損しました。間接的な影響として、別の関数の構造が次のようにシフトされたように見えました。数バイト。Mipsアセンブリコードを完全に読むなど、何が起こっているのかを理解するのにかなりの時間がかかりました。

于 2010-03-30T12:13:34.737 に答える
1

どのような設定をしているのかわかりませんが、次のシナリオでは、そのような効果(またはそれに類似した効果)を生み出すことができると思います。私はこれを検証するためにテストしていませんので、一粒の塩と一緒に服用してください。

開いているファイル/デバイスがサーバーアプリケーション(NFSなど)として実装されている場合は、サーバーアプリケーションがダウン/再起動/再起動した場合に何が起こるかを検討してください。ファイル記述子は、元々クライアント側で有効でしたが、サーバー側の有効なファイルハンドルにマップされなくなる可能性があります。これにより、クライアントがEBADFを取得する一連のイベントが発生する可能性があります。

お役に立てれば。

于 2010-03-30T12:47:36.893 に答える
0

いいえ、OSはそのようにファイルハンドルを閉じるべきではなく、他のアプリケーション(ファイルスキャナーなど)はそれを行うことができないはずです。

問題を回避しないでください。原因を見つけてください。問題の理由がわからない場合、回避策が実際に機能するかどうかはわかりません。

  1. あなたの仮定を確認してください。errno通話前に0に設定されていますか?呼び出しが行われている時点でfdは本当に有効ですか?(あなたがそう言ったのは知っていますが、あなたはそれをチェックしましたか?)
  2. puts( strerror( 9 ) );プラットフォームでの出力は何ですか?
于 2010-03-30T12:30:43.637 に答える