繁体   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