Cygwin のマルチプロセッシング モジュールからキューを作成しようとすると、奇妙な断続的なエラーが発生します。
Traceback (most recent call last):
File "test.py", line 3, in <module>
multiprocessing.Queue()
File "/usr/lib/python2.6/multiprocessing/__init__.py", line 213, in Queue
return Queue(maxsize)
File "/usr/lib/python2.6/multiprocessing/queues.py", line 37, in __init__
self._rlock = Lock()
File "/usr/lib/python2.6/multiprocessing/synchronize.py", line 117, in __init__
SemLock.__init__(self, SEMAPHORE, 1, 1)
File "/usr/lib/python2.6/multiprocessing/synchronize.py", line 49, in __init__
sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
OSError: [Errno 17] File exists
これを再現するための最小限のコードは次のとおりです。
import multiprocessing
multiprocessing.Queue()
ただし、エラーは約 25% の確率でしか発生しません。
現在、この問題を「解決」するためにQueue
、エラーが表示されなくなるまで s を継続的に作成する while ループがありますが、エラーが発生する理由を理解したいと思います。記載されているソース ファイルを調べてみましたが、c ソースまでさかのぼっても何の光も当てませんでした。
Windows 7 64ビットでCygwinからpython 2.6.7を実行しています。Cygwin からではなく、ネイティブの Windows python を介して cmd からこれを実行すると、問題は発生しません。
更新: ソースを詳しく見てみると、CreateSemaphore C 関数は "name" パラメーターを受け取るように見えます。この名前のセマフォが既に存在する場合は、エラーERROR_ALREADY_EXISTS
がフラグされます。ただし、Modules/_multiprocessing/semaphore.c の python ソースでは、この関数は name パラメータなしで呼び出されるため、これは発生しないはずです。これは、cygwin のセマフォ実装の癖にすぎないと思います。
Edit2:私は今、そのようなセットアップを持っています:
import multiprocessing
for i in range(10):
count = 0
while True:
try:
q = multiprocessing.Queue()
break
except OSError as exc:
if exc.errno == 17:
count += 1
else:
raise # catch other errors, but this has never happened
print "iterations %d" % count
私は奇妙な点に注意しました: Queue コンストラクターが失敗する回数は常に 3003 回以下であり、正確に 3000 回も頻繁に発生します。さらに、コンストラクターが一度成功すると、for ループの残りの繰り返しで再び失敗することはありません。
私はまだ困惑しています!gc.collect、time.sleep、キュー自体で close または del を呼び出してみましたが、これらのどれも影響を与えていないようです。これが実際にセマフォをクリーンアップするオペレーティングシステムに問題がある場合、システムコールを介してこれを「強制」する方法はありますか?