2

ここに非常にクールな問題があります。

私はPythonモジュール(foo.py)を呼び出すPythonスクリプト(メイン)を持っています。これは別のPythonモジュール(barwrapper.py)を呼び出し、LoadLibraryを使用してlibbar.soライブラリを動的に開いてアクセスします。

libbar とチェーンの残り全体が開いてファイルを作成し、タスクを実行します。インポートされたモジュールによって作成された一時ディレクトリを取り除くために、メインの python スクリプトで rmtree を発行すると、問題が発生します。rmtree は、スクリプトの最後、終了する直前に呼び出されます。.nfs-whateverディレクトリに隠しファイルが含まれているため、呼び出しは失敗します。これは、削除されたファイルであると思われます。.nfs-whateverこれらのファイルはコード内で開いたままになっているようで、ファイル記述子が解放されるまで、nfs はそれらをこれらのファイルに強制的に移動させます。この状況は他のファイルシステムでは発生しません。保持されている記述子に関連付けられているファイルは事実上削除されますが、記述子が閉じられるまでカーネルによってアクセス可能なままになるためです。

私たちは、.so ライブラリがファイル記述子をリークしていることを強く疑っています。これらの閉じられていないファイルは、クリーンアップ時に rmtree パーティを台無しにします。barwrapper で .so ファイルをアンロードすることを考えましたが、明らかにそれを行う方法はありません。また、dynloader が実際にプロセス空間から lib を削除して記述子を閉じるのか、それともアンロード済みとしてマークするだけなのかはわかりません。それだけで、他のものに置き換えられるのを待っていますが、記述子がリークされています。

この問題に対する他の回避策は本当に考えられません (リークの修正は別として、これはサードパーティのライブラリであるため、やりたくないことです)。明らかに、これは nfs でのみ発生します。私たちがそれを修正するために試すことができるアイデアはありますか?

4

2 に答える 2

1

カーネルはファイル記述子を追跡しているため、Python で .so をアンロードしてメモリを解放しても、リークしたファイル記述子を閉じることはできません。心に浮かぶ唯一のことは、フォーク後に.soをインポートし、フォークされた子プロセスが終了した後にのみクリーンアップすることです(そして、カーネルによって終了時にファイルハンドルが暗黙的に閉じられます)。

于 2011-05-19T00:38:21.713 に答える
1

適切な解決策は、ハンドル リークを修正することですが、誰がリークしているのかがわからない場合は、straceを呼び出してリークを特定し、サード パーティ ライブラリのメンテナーにバグを送信するのに役立つかもしれません (または、はオープン ソース ライブラリです。パッチを提出してみてください ;) )。

一方、nfs パーティションでの umount/mount は、ハンドルを強制的に閉じるのに役立つ可能性があります。

于 2011-05-18T18:39:51.397 に答える