Python でモジュールを使用して、ctypes
スレッド ローカル ストレージを含む共有 c-library をロードしています。これは長い歴史を持つ非常に大きな c-library であり、スレッドセーフにしようとしています。ライブラリには多くのグローバル変数と静的変数が含まれているため、スレッド セーフに対する最初の戦略は、スレッド ローカル ストレージを使用することでした。ライブラリをプラットフォームに依存しないようにしたいと考えており、win32、win64、および 64 ビット Ubuntu の両方でスレッド セーフをコンパイルおよびテストしています。純粋な c プロセスからは、問題はないようです。
ただし、win32 および Ubuntu の Python (2.6 および 2.7) では、メモリ リークが発生しています。Python スレッドが終了したときに、スレッド ローカル ストレージが適切に解放されていないようです。または、少なくとも、メモリが解放されたことをpythonプロセスが「認識」していないということです。同じ問題は、実際には win32 の ac#-program でも見られますが、win64 サーバー テスト マシン (python 2.7 も実行) には存在しません。
この問題は、次のような単純なおもちゃの例で再現できます。
以下を含む c ファイルを作成します (linux/unix
削除__declspec(dllexport)
時):
#include <stdio.h>
#include <stdlib.h>
void __declspec(dllexport) Leaker(int tid){
static __thread double leaky[1024];
static __thread int init=0;
if (!init){
printf("Thread %d initializing.", tid);
int i;
for (i=0;i<1024;i++) leaky[i]=i;
init=1;}
else
printf("This is thread: %d\n",tid);
return;}
MINGW
次のように、Linux の Windows/gcc でウィットをコンパイルします。
gcc -o leaky.dll
(またはleaky.so
)-shared the_file.c
Windows では、Visual Studio でコンパイルして__thread
、__declspec(thread)
. ただし、win32 (winXP までだと思います) では、ライブラリを実行時に .xml でロードする場合、これは機能しませんLoadLibrary
。
次のような python プログラムを作成します。
import threading, ctypes, sys, time
NRUNS=1000
KEEP_ALIVE=5
REPEAT=2
lib=ctypes.cdll.LoadLibrary("leaky.dll")
lib.Leaker.argtypes=[ctypes.c_int]
lib.Leaker.restype=None
def UseLibrary(tid,repetitions):
for i in range(repetitions):
lib.Leaker(tid)
time.sleep(0.5)
def main():
finished_threads=0
while finished_threads<NRUNS:
if threading.activeCount()<KEEP_ALIVE:
finished_threads+=1
thread=threading.Thread(target=UseLibrary,args=(finished_threads,REPEAT))
thread.start()
while threading.activeCount()>1:
print("Active threads: %i" %threading.activeCount())
time.sleep(2)
return
if __name__=="__main__":
sys.exit(main())
エラーを再現するにはこれで十分です。ガベージ コレクターを明示的にインポートしcollect gc.collect()
ます。新しいスレッドを開始するたびに a を実行しても効果はありません。
しばらくの間、この問題は互換性のないランタイム (Visual Studio でコンパイルされた Python、私のライブラリではMINGW
) に関係していると考えていました。しかし、問題はUbuntuにもありますが、ライブラリがMINGW
.
誰でも助けてくれることを願っています!
乾杯、Simon Kokkendorff、National Survey and Cadastre of Denmark。