| 1 | import zope.interface |
|---|
| 2 | import twisted.plugin |
|---|
| 3 | import cPickle as pickle |
|---|
| 4 | from twisted.spread import pb |
|---|
| 5 | from twisted.internet import defer, protocol, reactor |
|---|
| 6 | from twisted.python import log |
|---|
| 7 | |
|---|
| 8 | class PP(protocol.ProcessProtocol): |
|---|
| 9 | def __init__(self, processdone): |
|---|
| 10 | self.output = "" |
|---|
| 11 | self.d_connected = defer.Deferred() |
|---|
| 12 | self.d_connected.addCallback(log.msg) |
|---|
| 13 | self.d_connected.addErrback(log.err) |
|---|
| 14 | self.processdone = processdone |
|---|
| 15 | |
|---|
| 16 | def connectionMade(self): |
|---|
| 17 | self.transport.closeStdin() |
|---|
| 18 | self.d_connected.callback("Connected") |
|---|
| 19 | |
|---|
| 20 | def outReceived(self, data): |
|---|
| 21 | pass |
|---|
| 22 | |
|---|
| 23 | def errReceived(self, data): |
|---|
| 24 | log.err(data) |
|---|
| 25 | |
|---|
| 26 | def processEnded(self, status): |
|---|
| 27 | self.transport.loseConnection() |
|---|
| 28 | self.processdone.callback("all done") |
|---|
| 29 | |
|---|
| 30 | def die(self): |
|---|
| 31 | log.msg("Kill %s:%d" % (self.name, self.transport.pid)) |
|---|
| 32 | os.kill(self.transport.pid, signal.SIGKILL) |
|---|
| 33 | |
|---|
| 34 | |
|---|
| 35 | class TimingOutCommand: |
|---|
| 36 | def __init__(self, timeout, command, args): |
|---|
| 37 | self.done = defer.Deferred() |
|---|
| 38 | self.done.addCallback(self._canceltimeout_cmd) |
|---|
| 39 | self.done.addErrback(log.err) |
|---|
| 40 | self.timeout = timeout |
|---|
| 41 | self.command = command |
|---|
| 42 | self.args = args |
|---|
| 43 | self.connector = PP(self.done) |
|---|
| 44 | env = os.environ |
|---|
| 45 | args = [command, self.args] |
|---|
| 46 | reactor.spawnProcess(self.connector, command, args, env=env) |
|---|
| 47 | self.canceltimeout = False |
|---|
| 48 | reactor.callLater(timeout, self._timeout_cmd) |
|---|
| 49 | |
|---|
| 50 | def _timeout_cmd(self): |
|---|
| 51 | if self.canceltimeout: |
|---|
| 52 | log.msg("Trying to timeout command, but timeout was cancelled") |
|---|
| 53 | return |
|---|
| 54 | log.msg("Timed out before it could finish") |
|---|
| 55 | self.timeout_cmd() |
|---|
| 56 | |
|---|
| 57 | def _canceltimeout_cmd(self, result): |
|---|
| 58 | self.canceltimeout = True |
|---|
| 59 | self.canceltimeout_cmd() |
|---|
| 60 | |
|---|
| 61 | def conceltimeout_cmd(self): |
|---|
| 62 | raise NotImplementedError |
|---|
| 63 | |
|---|
| 64 | def timeout_cmd(self): |
|---|
| 65 | raise NotImplementedError |
|---|
| 66 | |
|---|
| 67 | class CmdTimeout(TimingOutCommand): |
|---|
| 68 | def __init__(self, timeout, command, args): |
|---|
| 69 | TimingOutCommand.__init__(self, timeout, command, args) |
|---|
| 70 | |
|---|
| 71 | def canceltimeout_cmd(self): |
|---|
| 72 | pass |
|---|
| 73 | |
|---|
| 74 | def timeout_cmd(self): |
|---|
| 75 | log.msg("cancelling!!!") |
|---|
| 76 | |
|---|
| 77 | if __name__ == "__main__": |
|---|
| 78 | log.FileLogObserver.timeFormat = '[%d/%b/%Y:%H:%M:%S]' |
|---|
| 79 | log.startLogging(sys.stdout) |
|---|
| 80 | a = CmdTimeout(3, "/bin/sleep", "10") |
|---|
| 81 | reactor.run() |
|---|