7

モジュールを使用してコード ブロックのタイムアウトを強制しmultiprocessingます。特定のサイズの入力で、次のエラーが発生するようです。

WindowsError: [Error 5] Access is denied

次のコードでこのエラーを再現できます。コードは '467,912,040' で完了しますが、'517,912,040' で完了しないことに注意してください。

import multiprocessing, Queue

def wrapper(queue, lst):
    lst.append(1)
    queue.put(lst)
    queue.close()

def timeout(timeout, lst):
    q = multiprocessing.Queue(1)
    proc = multiprocessing.Process(target=wrapper, args=(q, lst))
    proc.start()
    try:
        result = q.get(True, timeout)
    except Queue.Empty:
        return None
    finally:
        proc.terminate()
    return result

if __name__ == "__main__":
    # lst = [0]*417912040 # this works fine
    # lst = [0]*467912040 # this works fine
    lst = [0] * 517912040 # this does not
    print "List length:",len(lst)
    timeout(60*30, lst)

出力 (エラーを含む):

List length: 517912040

Traceback (most recent call last):
  File ".\multiprocessing_error.py", line 29, in <module>
    print "List length:",len(lst)
  File ".\multiprocessing_error.py", line 21, in timeout
    proc.terminate()
  File "C:\Python27\lib\multiprocessing\process.py", line 137, in terminate
    self._popen.terminate()
  File "C:\Python27\lib\multiprocessing\forking.py", line 306, in terminate
    _subprocess.TerminateProcess(int(self._handle), TERMINATE)
WindowsError: [Error 5] Access is denied

特定のサイズのプロセスを終了することはできませんか?

Windows 7 (64 ビット) で Python 2.7 を使用しています。

4

1 に答える 1

8

問題の正確な原因についてはまだ不明ですが、いくつかの追加の観察と回避策があります。

回避策。

try-exceptfinally 句にブロックを追加します。

finally:
    try:
        proc.terminate()
    except WindowsError:
        pass

これは、ここ GitHub に投稿された関連する (?) イシュー(少し下にスクロールする必要があるかもしれません) で得られた解決策でもあるようです。

観察。

  1. このエラーは、プロセス/キューに渡されたオブジェクトのサイズに依存しますが、プロセス自体の実行には関係ありません。OP では、プロセスはタイムアウトになる前に完了します。
  2. proc.is_aliveTrueの実行前後に戻りますproc.terminate()(その後、WindowsError がスローされます)。1 ~ 2 秒後にproc.is_alive()戻りFalse、2 回目の呼び出しがproc.terminate()成功します。
  3. ブロック内でメイン スレッドを強制的にスリープtime.sleep(1)させるfinallyと、WindowsError のスローも防止されます。ありがとう、OPでの@tdelaneyのコメント。
  4. 私の最善の推測は、呼び出しが再びそれを殺そうとしprocたときに、OSによって殺されている間(実行が完了したとき)、メモリを解放する過程にあることです(?、またはそれに匹敵するもの) 。proc.terminate()
于 2013-06-18T20:25:44.627 に答える