奇怪的线程行为

时间:2012-01-06 19:32:14

标签: python multithreading

我是python的新手,但不是多线程软件,所以我无法解释我所看到的特定行为。我的程序非常简单:我监视linux命令'iostat'的输出并在某些情况下执行某些操作。我的代码如下:

class SysMonitor(threading.Thread):

def __init__(self):
    threading.Thread.__init__(self)
    self.isStopping = False
    self.ioprocess = []

def run(self):
    self.ioprocess = subprocess.Popen(['/usr/bin/iostat', '-p', 'sda', '60'], stdout=subprocess.PIPE)
    p = self.ioprocess
    i = 0

    # Discard first output
    while (i < 11):
        p.stdout.readline()
        i = i + 1

    # Now keep on waiting on new output from iostat and then process it when it comes in
    while (not self.isStopping):
        select.select([p.stdout], [], [])

        # Don't process the last output if we are stopping
        if (self.isStopping):
            print 'Quitting, discarding last buffer:' + str(self.isStopping)
            continue

        # do some p.stdout.readline() and process the data

def stop(self):
    self.isStopping = True
    self.ioprocess.terminate()

我不明白的是,当我调用'stop'函数时,程序有时会崩溃因为select被释放,因为EOF是在stdout缓冲区中写的,但isStopping仍然是False。怎么会发生这种情况?

3 个答案:

答案 0 :(得分:2)

如果在线程外调用stop(),则可能导致随机问题。因为当你调用stop()时,线程无论如何都可以是打印,还是选择等等。

只需在terminate()方法的末尾移动run()即可。然后将isStopping设置为True将正确地离开循环,然后终止该过程。

如果您想等待它,可以加入以下内容:

def stop(self):
    self.isStopping = True
    self.join()

答案 1 :(得分:2)

tito's answer为基础,关于您的评论,您可以在select.select中使用超时:

    while (not self.isStopping):
        ready, _, _ = select.select([p.stdout], [], [], 5.0)

        # Don't process the last output if we are stopping
        if (self.isStopping):
            print 'Quitting, discarding last buffer:' + str(self.isStopping)
            continue
        if ready:
            # do some p.stdout.readline() and process the data

    self.ioprocess.terminate()

以上,超时为5.0秒。我认为这足够长,不会锤击系统,并且足够短以便合理终止。改变以适合您的口味。

答案 2 :(得分:0)

如果目标是在应用程序结束时结束线程,则将线程设置为守护进程。