调用Process.terminate时出现"WindowsError:Access被拒绝"

Dav*_*d C 7 python windowserror multiprocessing

我使用该multiprocessing模块强制执行代码块的超时.看来,对于某些大小的输入,会引发以下错误:

WindowsError: [Error 5] Access is denied
Run Code Online (Sandbox Code Playgroud)

我可以使用以下代码复制此错误.请注意,代码以'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)
Run Code Online (Sandbox Code Playgroud)

输出(包括错误):

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
Run Code Online (Sandbox Code Playgroud)

我不允许终止一定规模的流程吗?

我在Windows 7(64位)上使用Python 2.7.

Dav*_*d C 7

虽然我仍然不确定问题的确切原因,但我还有一些额外的观察和解决方法.

解决方法.

try-except在finally子句中添加块.

finally:
    try:
        proc.terminate()
    except WindowsError:
        pass
Run Code Online (Sandbox Code Playgroud)

这也似乎是在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. 我最好的猜测是,procproc.terminate()尝试再次杀死它的同时被操作系统(已完成执行)杀死时,正在释放内存(?或类似的东西).