簡體   English   中英

嘗試終止線程上運行的python子進程時的行為不一致

[英]Inconsistent behavior when attempting to terminate python subprocess running on a thread

當我嘗試終止在單獨線程上運行的長時間運行的進程時,我遇到了問題。

下面是程序。 WorkOne創建一個子進程並運行一個長時間運行的進程“ adb logcat”,該進程會生成日志行。 我在main()中啟動WorkOne,等待5秒鍾,然后嘗試將其停止。 多次運行可提供多個輸出

import threading
import time
import subprocess
import sys

class WorkOne(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()  
        self.process = subprocess.Popen(['adb','logcat'], stdout=subprocess.PIPE, stderr=sys.stdout.fileno())      

    def run(self):   
        for line in iter(self.process.stdout.readline,''):            
            #print line
            if self.event.is_set():
                self.process.terminate()
                self.process.kill()
                break;
        print 'exited For'

    def stop(self):
        self.event.set()

def main():

    print 'starting worker1'
    worker1 = WorkOne()
    worker1.start()
    print 'number of threads: ' + str(threading.active_count())
    time.sleep(5)
    worker1.stop()
    worker1.join(5)
    print 'number of threads: ' + str(threading.active_count())

if __name__ == '__main__':
    main()

有時我得到[A]:

starting worker1
number of threads: 2
number of threads: 2
exited For

有時我得到[B]:

starting worker1
number of threads: 2
number of threads: 1
exited For

有時我得到[C]:

starting worker1
number of threads: 2
number of threads: 2

我想我應該一直得到[B]。 這是怎么了?

更改

       if self.event.is_set():
            self.process.terminate()
            self.process.kill()
            break;

        if self.event.is_set():
            self.process.terminate()
            self.process.wait()
            break

分號是一個死胡同,這里有一個問題。

我猜想,沒有wait()的線程有時會work1.join(5)解除對work1.join(5)work1.join(5) 在這些情況下, threading.active_count()返回2。

而且,正如@ A.Rodas所說, work1.join(5)應該是work1.join()以確保在work1完成之前,連接不會解除阻塞。


順便說一句,我不確定您為什么要調用terminate然后連續kill 在Unix上,kill是更嚴重的終止形式。 在Windows上,它們是相同的。 因此,如果要呼叫kill,則無需呼叫終止。

由於您知道subprocess調用的程序,因此您也應該知道終止是否足以停止它。

因此,您只需要一個: self.process.terminate()self.process.kill()

我認為[B]僅在子進程少於10秒的情況下才可能:主線程休眠5秒,然后該worker線程在join()的5秒超時內完成操作。

在10秒鍾或更長時間內, worker即使在join()調用之后仍可以存活,因為它具有超時參數,這可能會發生也可能不會發生。 然后,您可以獲得[A](子過程在幾秒鍾后完成)或[C](子過程在很晚之后完成)。

要始終獲取[B],請刪除join()的超時參數,以便主線程等待直到worker完成為止(或通過將kill調用置於循環外部來確保在10秒內終止該進程)。

暫無
暫無

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

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