私はPythonのctypesモジュールを使用してライブラリをロードすることで、ビジネスソフトウェアのベンダーのC APIを使用しています。Pythonで使用されているベンダーのDLLでメモリリークを回避するには?
私が書いたソフトウェアをデプロイした後、APIの一部である特定の関数の呼び出し回数に応じて、ベンダーのライブラリが一貫した予測可能な基準でメモリをリークすることがわかりました。
ヒープ割り当てを使用しないCプログラムでもリークが重複していました。
私はこの問題についてベンダーに連絡し、彼らはそれに取り組んでいると言いましたが、次のバージョンのソフトウェアまで現実的には修正を期待できません。
私はリーク関数の呼び出しの特定のしきい値の後、ベンダーのdllをリロードする考えがありましたが、これは漏れたメモリを解放しませんでした。
が、私はそうのようにアンロードするライブラリを強制することが分かっ:
_ctypes.FreeLibrary(vendor_dll._handle)
これは、メモリを解放しますが、ベンダーのAPIを使用しての分の数の後に、一見ランダムにクラッシュするインタプリタの原因となります。
私は私の状況を説明し、Pythonのバグトラッカーでこの問題を発見した: https://bugs.python.org/issue14597
ライブラリへのオープン参照が残っていた場合には、アンロードすることを強制することは必然的にPythonインタプリタをクラッシュするようです。
最悪のシナリオでは、ベンダーのライブラリを別のプロセスで読み込み、マルチプロセッシングキューを使用してプロキシ要求を行い、インタープリタが終了した場合にプロセスを再構築するためにウォッチドッグをセットアップできます。
これを回避するより良い方法はありますか?
上記の回避策のより洗練された解決策は、定期的な間隔でワーカープロセスを終了して再起動することです。これにより、ベンダーのライブラリによって漏洩されたメモリは解放されますが、インタプリタはクラッシュしません。 – jakogut
ライブラリを解放すると、実際にはメモリリークではありません。ライブラリは 'DLL_PROCESS_DETACH'で解放するためにこれらの割り当てを追跡しなければなりません。 'vendor_dll'をアンロードするには、まず現在のインスタンスへの参照をすべて削除し、未処理の非同期コールバックを含め、コードを再度実行しないようにしてください。その後、DLLをアンロードして再ロードすることができます。共有ライブラリは参照カウントされるので、実際にアンロードされるようにするには 'OSError'が発生するまで' FreeLibrary'を呼び出します。 – eryksun