试图终止在线程上运行的python子进程时的不一致行为



当我试图终止在单独线程上运行的长时间运行的进程时,我遇到了问题。

程序如下。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]所有的时间。这里出了什么问题?

我认为[B]只有在子进程花费少于10秒的情况下才有可能:主线程休眠5秒,之后workerjoin()的5秒超时内完成。

即使在join()调用之后,worker也可以存活10秒或更长时间,因为它有一个超时参数,这可能发生也可能不发生。然后你可以得到[A](子进程几秒钟后完成)或[C](子进程完成得很晚)。

要获得always [B],请删除join()的timeout参数,以便主线程等待worker完成(或者通过在循环外放置kill调用确保在10秒内终止进程)。

变化

       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)太快。在这些情况下,threading.active_count()返回2。

,为@A。Rodas说,work1.join(5)应该是work1.join(),以确保连接在work1完成之前不会解除阻塞。


顺便说一下,我不确定为什么你想要连续调用terminate然后kill。在Unix上,kill是一种更严重的终止形式。在Windows上,它们是相同的。因此,如果你要调用kill,就不需要调用terminate。

既然你知道subprocess调用的程序,你也应该知道terminate是否足以停止它。

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

相关内容

  • 没有找到相关文章

最新更新