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-except在 finally 子句中添加一个块。

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

这似乎也是GitHub 上发布的相关(?)问题中的解决方案(您可能需要向下滚动一点)。

观察。

  1. 此错误取决于传递给 Process/Queue 的对象的大小,但与 Process 本身的执行无关。在 OP 中,进程在超时到期之前完成。
  2. proc.is_aliveTrue在执行之前和之后返回proc.terminate()(然后抛出 WindowsError)。一两秒钟后,proc.is_alive()返回False并且第二次调用proc.terminate()成功。
  3. 强制主线程time.sleep(1)finally块中休眠也可以防止抛出 WindowsError。谢谢,@tdelaney 在 OP 中的评论。
  4. 我最好的猜测是,当调用试图再次杀死它时,它proc正在释放内存(?或类似的东西),同时被操作系统杀死(已完成执行) 。proc.terminate()
于 2013-06-18T20:25:44.627 回答