簡體   English   中英

生產者異常終止時Python多處理隊列死鎖

[英]Python multiprocessing queue deadlock when producer terminates with exception

我使用的是Python 2.7 multiprocessing.Queue ,其父進程是隊列的“生產者”(即任務“調度程序”),子進程是隊列的使用者(即“工人”進程)。 我需要子進程是非“守護程序”的,以便在父進程中發生異常時,它不會中斷子進程對現有隊列項目的處理。 但是,我發現,如果父進程中發生異常,則會發生死鎖,因為父進程嘗試加入子進程,而一旦清空隊列,子進程將永遠等待更多隊列項。 另一方面,如果我將子進程設置為“守護進程”,則當父進程因異常終止時,子進程將立即終止,這會中斷子進程對現有隊列項目的處理。

演示示例(使用非守護程序子進程):

import multiprocessing, time

def childProcessFunction(sharedQueue):
    # Consumer loop
    while True:
        print "Child process: Consuming item.  We will deadlock here if the queue is empty and the parent process has terminated!"
        consumedItem=sharedQueue.get()

        print "Child process: Taking some time to process the consumed item..."
        time.sleep(5)
        print consumedItem # Do something with (print) the consumed item.
        time.sleep(5)
        print "Child process: Done processing the consumed item; re-looping to get another item..."

def parentProcessMain():
    sharedQueue=multiprocessing.Queue()

    childProcess=multiprocessing.Process(target=childProcessFunction, args=(sharedQueue,))

    # Don't want a daemon process because we don't want to interrupt the child's 
    # processing of existing items when the parent process terminates.
    childProcess.daemon=False

    print "Parent process: Starting child process..."
    childProcess.start()

    failAfter=3 # Simulate a failure after producing 3 items.

    numDispatched=0 # Number of items put onto the queue.

    # Producer loop
    while True:
        time.sleep(3)

        if failAfter==0:
            raise Exception("Parent process encountered a failure of some kind and is exiting uncleanly!  Now the parent process will try to join the child process, and the child process will deadlock once the queue is empty!")

        producedItem="This is item number: %d"%numDispatched
        print "Parent process: Enqueueing item number %d..."%numDispatched
        sharedQueue.put(producedItem)
        numDispatched+=1
        failAfter-=1
        time.sleep(3)

if __name__=="__main__":
    parentProcessMain()

有沒有一種方法可以讓子進程在父進程獲得異常(非守護行為)之后完成正在進行中的處理以及隊列中剩余的所有內容,但是阻止子進程等待此后永遠排隊嗎? 有沒有一種方法可以使隊列“意識到”生產者已經終止並在get()上引發異常而不是無限期地阻塞這一事實?

請注意,如果隊列碰巧是空的,並且當父進程獲得異常時子進程正在等待get()調用,那么在這種情況下(大概有異常),我需要get()終止。

在知道子進程完成之前,您是否可以保留例外? 也許通過某種形式的同步,例如互斥鎖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM