简体   繁体   English

在python中实现看门狗计时器的工具

[英]Tools for implementing a watchdog timer in python

I'm writing some code for testing multithreaded programs (student homework--likely buggy), and want to be able to detect when they deadlock. 我正在编写一些代码来测试多线程程序(学生作业-可能是越野车),并希望能够检测到它们何时死锁。 When running properly, the programs regularly produce output to stdout, so that makes it fairly straightforward: if no output for X seconds, kill it and report deadlock. 正常运行时,程序会定期向stdout生成输出,因此非常简单:如果X秒钟没有输出,请杀死它并报告死锁。 Here's the function prototype: 这是函数原型:

def run_with_watchdog(command, timeout):
    """Run shell command, watching for output.  If the program doesn't
     produce any output for <timeout> seconds, kill it and return 1.  
     If the program ends successfully, return 0."""

I can write it myself, but it's a bit tricky to get right, so I would prefer to use existing code if possible. 我可以自己编写它,但是正确起来有点棘手,所以如果可能的话,我宁愿使用现有代码。 Anyone written something similar? 有人写过类似的东西吗?


Ok, see solution below. 好的,请参阅下面的解决方案。 The subprocess module might also be relevant if you're doing something similar. 如果您正在执行类似的操作,则子流程模块也可能是相关的。

You can use expect (tcl) or pexpect (python) to do this. 您可以使用Expect(tcl)或pexpect(python)来执行此操作。

import pexpect
c=pexpect.spawn('your_command')
c.expect("expected_output_regular_expression", timeout=10)

Here's a very slightly tested, but seemingly working, solution: 这是一个经过稍微测试但似乎可行的解决方案:

import sys
import time
import pexpect
# From http://pypi.python.org/pypi/pexpect/

DEADLOCK = 1

def run_with_watchdog(shell_command, timeout):
    """Run <shell_command>, watching for output, and echoing it to stdout.
    If the program doesn't produce any output for <timeout> seconds,
    kill it and return 1.  If the program ends successfully, return 0.
    Note: Assumes timeout is >> 1 second. """

    child = pexpect.spawn('/bin/bash', ["-c", shell_command])
    child.logfile_read = sys.stdout
    while True:
        try:
            child.read_nonblocking(1000, timeout)
        except pexpect.TIMEOUT:
            # Child seems deadlocked.  Kill it, return 1.
            child.close(True)
            return DEADLOCK
        except pexpect.EOF:
            # Reached EOF, means child finished properly.
            return 0
        # Don't spin continuously.
        time.sleep(1)

if __name__ == "__main__":
    print "Running with timer..."
    ret = run_with_watchdog("./test-program < trace3.txt", 10) 
    if ret == DEADLOCK:
        print "DEADLOCK!"
    else:
        print "Finished normally"

Another solution: 另一个解决方案:

class Watchdog:
  def __init__(self, timeout, userHandler=None): # timeout in seconds
    self.timeout = timeout
    if userHandler != None:
      self.timer = Timer(self.timeout, userHandler)
    else:
      self.timer = Timer(self.timeout, self.handler)

  def reset(self):
    self.timer.cancel()
    self.timer = Timer(self.timeout, self.handler)

  def stop(self):
    self.timer.cancel()

  def handler(self):
    raise self;

Usage if you want to make sure function finishes in less than x seconds: 如果要确保功能在不到x秒内完成,请使用:

watchdog = Watchdog(x)
try
  ... do something that might hang ...
except Watchdog:
  ... handle watchdog error ...
watchdog.stop()

Usage if you regularly execute something and want to make sure it is executed at least every y seconds: 如果您定期执行某件事并希望至少每y秒执行一次,请使用此方法:

def myHandler():
  print "Watchdog expired"

watchdog = Watchdog(y, myHandler)

def doSomethingRegularly():
  ...
  watchdog.reset()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM