2013-06-12 77 views
5

我使用multiprocessing模塊強制執行一段代碼超時。看起來,對於特定大小的輸入,會出現以下錯誤:調用Process.terminate時出現「WindowsError:Access is denied」

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。

+1

我不認爲你會激怒蟒蛇......但是它是一個很大的列表,你想要傳輸,並且你可能會在子進程處於奇怪狀態時超時(可能還沒有開始)。只是酸洗你的清單花了70秒在我的系統上。當終止失敗時可以打印句柄,並查看過程是否存在。也許你可以睡一會兒再試一次。 – tdelaney

+1

看起來問題與'len(lst)'調用有關,這可能是因爲'隊列'已被損壞。在terminate()'[documentation](http://docs.python.org/2/library/multiprocessing.html?highlight=terminate#multiprocessing.Process.terminate)中突出顯示了這種情況是有可能發生的。 – martineau

回答

5

雖然我仍然不確定問題的確切原因,但我還是有一些額外的觀察以及解決方法。

解決方法。

在finally子句中添加try-except塊。

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

這也似乎是解決在相關抵達(?)問題發佈here on GitHub(您可能需要向下滾動一點)。

觀察。

  1. 此錯誤取決於傳遞給過程/隊列的物體的大小,但它是不相關的過程本身的執行。在OP中,進程在超時到期之前完成。
  2. proc.is_alive返回True之前和之後執行proc.terminate()(然後引發WindowsError)。一秒或兩秒後,proc.is_alive()返回False,第二次呼叫proc.terminate()成功。
  3. 強制主線程在finally塊中睡眠time.sleep(1)也可以防止拋出WindowsError。謝謝@ tdelaney在OP的評論。
  4. 我最好的猜測是proc正在釋放內存(?,或類似的東西),同時被操作系統殺死(完成執行),當proc.terminate()的呼叫試圖再次殺死它時。
相關問題