def runProcess(args, timeout, grace, reactor):
deferred = defer.Deferred()<EOL>protocol = ProcessProtocol(deferred)<EOL>process = reactor.spawnProcess(protocol, args[<NUM_LIT:0>], args, env=os.environ)<EOL>def _logEnded(err):<EOL><INDENT>err.trap(tierror.ProcessDone, tierror.ProcessTerminated)<EOL>print(err.value)<EOL><DEDENT>deferred.addErrback(_logEnded)<EOL>def _cancelTermination(dummy):<EOL><INDENT>for termination in terminations:<EOL><INDENT>if termination.active():<EOL><INDENT>termination.cancel()<EOL><DEDENT><DEDENT><DEDENT>deferred.addCallback(_cancelTermination)<EOL>terminations = []<EOL>terminations.append(reactor.callLater(timeout, process.signalProcess,<EOL>"<STR_LIT>"))<EOL>terminations.append(reactor.callLater(timeout+grace,<EOL>process.signalProcess, "<STR_LIT>"))<EOL>return deferred<EOL>
Run a process, return a deferred that fires when it is done

    :params args: Process arguments
    :params timeout: Time before terminating process
    :params grace: Time before killing process after terminating it
    :params reactor: IReactorProcess and IReactorTime
    :returns: deferred that fires with success when the process ends,
              or fails if there was a problem spawning/terminating
              the process