[Twisted-web] spawning a xvfb and firefox with a timeout

exarkun at twistedmatrix.com exarkun at twistedmatrix.com
Mon Aug 22 15:53:34 EDT 2011

On 04:32 pm, schenette at gmail.com wrote:
>I think I might have figured out that you have to add usePTY=1 to
>associate the process group, so that the children will be killed when
>the parent process is killed.
>subprocess = reactor.spawnProcess(self.pp, args[0], args, env = os.e
>nviron, usePTY=1)

This is a not bad approach.  Another possibility might be to leave 
usePTY out but change how you kill the process.  There is the notion of 
"process groups", which contain one or more processes, and all of the 
processes in a group can be sent a signal by passing a negative number 
to os.kill.  For your case, the process group would probably be the same 
as the pid of the xvfb-run process, so you could do something like:

    os.kill(-process.transport.pid, SIGTERM)

Whether this is better or worse than using a PTY depends on the 
particulars of how xvfb-run manages its child process, whether it is 
okay to actually have a pty allocated, and probably some other POSIX 
>but I tried to separate out the killing in another process and now the
>new method isnt' called.
>are ProcessProtocol classes allowed to have other methods added to it
>for calling?
>45     def killProcessIfAlive(self):
>46         logging.debug("killProcessIfAlive called")
>47         try:
>48             yield self.transport.signalProcess('KILL')
>49         except error.ProcessExitedAlready:
>50             logging.debug("process already exited")
>51             pass

It looks like you wanted killProcessIfAlive to be decorated with 
inlineCallbacks, but I don't see that here.  So that would prevent the 
signal from ever actually being sent.  signalProcess doesn't return a 
Deferred though, so you can skip inlineCallbacks and the yield and that 
should also fix the problem.
>53     def connectionMade(self):
>54         logging.debug("connection made timeout = %d", self.timeout)
>55         @defer.inlineCallbacks
>56         def onTimer():
>57             logging.debug("timeout triggered")
>58             self.killProcessIfAlive()
>59         d = reactor.callLater(self.timeout, onTimer)

Ah, there's the inlineCallbacks.  It won't work there, though, it needs 
to go onto the generator function (the function that has yield in it).


More information about the Twisted-web mailing list