| Index: third_party/mozprocess/README.md
|
| ===================================================================
|
| --- third_party/mozprocess/README.md (revision 0)
|
| +++ third_party/mozprocess/README.md (revision 0)
|
| @@ -0,0 +1,168 @@
|
| +[mozprocess](https://github.com/mozilla/mozbase/tree/master/mozprocess)
|
| +provides python process management via an operating system
|
| +and platform transparent interface to Mozilla platforms of interest.
|
| +Mozprocess aims to provide the ability
|
| +to robustly terminate a process (by timeout or otherwise), along with
|
| +any child processes, on Windows, OS X, and Linux. Mozprocess utilizes
|
| +and extends `subprocess.Popen` to these ends.
|
| +
|
| +
|
| +# API
|
| +
|
| +[mozprocess.processhandler:ProcessHandler](https://github.com/mozilla/mozbase/blob/master/mozprocess/mozprocess/processhandler.py)
|
| +is the central exposed API for mozprocess. `ProcessHandler` utilizes
|
| +a contained subclass of [subprocess.Popen](http://docs.python.org/library/subprocess.html),
|
| +`Process`, which does the brunt of the process management.
|
| +
|
| +## Basic usage
|
| +
|
| + process = ProcessHandler(['command', '-line', 'arguments'],
|
| + cwd=None, # working directory for cmd; defaults to None
|
| + env={}, # environment to use for the process; defaults to os.environ
|
| + )
|
| + process.run(timeout=60) # seconds
|
| + process.wait()
|
| +
|
| +`ProcessHandler` offers several other properties and methods as part of its API:
|
| +
|
| + def __init__(self,
|
| + cmd,
|
| + args=None,
|
| + cwd=None,
|
| + env=None,
|
| + ignore_children = False,
|
| + processOutputLine=(),
|
| + onTimeout=(),
|
| + onFinish=(),
|
| + **kwargs):
|
| + """
|
| + cmd = Command to run
|
| + args = array of arguments (defaults to None)
|
| + cwd = working directory for cmd (defaults to None)
|
| + env = environment to use for the process (defaults to os.environ)
|
| + ignore_children = when True, causes system to ignore child processes,
|
| + defaults to False (which tracks child processes)
|
| + processOutputLine = handlers to process the output line
|
| + onTimeout = handlers for timeout event
|
| + kwargs = keyword args to pass directly into Popen
|
| +
|
| + NOTE: Child processes will be tracked by default. If for any reason
|
| + we are unable to track child processes and ignore_children is set to False,
|
| + then we will fall back to only tracking the root process. The fallback
|
| + will be logged.
|
| + """
|
| +
|
| + @property
|
| + def timedOut(self):
|
| + """True if the process has timed out."""
|
| +
|
| +
|
| + def run(self, timeout=None, outputTimeout=None):
|
| + """
|
| + Starts the process.
|
| +
|
| + If timeout is not None, the process will be allowed to continue for
|
| + that number of seconds before being killed.
|
| +
|
| + If outputTimeout is not None, the process will be allowed to continue
|
| + for that number of seconds without producing any output before
|
| + being killed.
|
| + """
|
| +
|
| + def kill(self):
|
| + """
|
| + Kills the managed process and if you created the process with
|
| + 'ignore_children=False' (the default) then it will also
|
| + also kill all child processes spawned by it.
|
| + If you specified 'ignore_children=True' when creating the process,
|
| + only the root process will be killed.
|
| +
|
| + Note that this does not manage any state, save any output etc,
|
| + it immediately kills the process.
|
| + """
|
| +
|
| + def readWithTimeout(self, f, timeout):
|
| + """
|
| + Try to read a line of output from the file object |f|.
|
| + |f| must be a pipe, like the |stdout| member of a subprocess.Popen
|
| + object created with stdout=PIPE. If no output
|
| + is received within |timeout| seconds, return a blank line.
|
| + Returns a tuple (line, did_timeout), where |did_timeout| is True
|
| + if the read timed out, and False otherwise.
|
| +
|
| + Calls a private member because this is a different function based on
|
| + the OS
|
| + """
|
| +
|
| + def processOutputLine(self, line):
|
| + """Called for each line of output that a process sends to stdout/stderr."""
|
| + for handler in self.processOutputLineHandlers:
|
| + handler(line)
|
| +
|
| + def onTimeout(self):
|
| + """Called when a process times out."""
|
| + for handler in self.onTimeoutHandlers:
|
| + handler()
|
| +
|
| + def onFinish(self):
|
| + """Called when a process finishes without a timeout."""
|
| + for handler in self.onFinishHandlers:
|
| + handler()
|
| +
|
| + def wait(self, timeout=None):
|
| + """
|
| + Waits until all output has been read and the process is
|
| + terminated.
|
| +
|
| + If timeout is not None, will return after timeout seconds.
|
| + This timeout only causes the wait function to return and
|
| + does not kill the process.
|
| + """
|
| +
|
| +See https://github.com/mozilla/mozbase/blob/master/mozprocess/mozprocess/processhandler.py
|
| +for the python implementation.
|
| +
|
| +`ProcessHandler` extends `ProcessHandlerMixin` which by default prints the
|
| +output, logs to a file (if specified), and stores the output (if specified, by
|
| +default `True`). `ProcessHandlerMixin`, by default, does none of these things
|
| +and has no handlers for `onTimeout`, `processOutput`, or `onFinish`.
|
| +
|
| +`ProcessHandler` may be subclassed to handle process timeouts (by overriding
|
| +the `onTimeout()` method), process completion (by overriding
|
| +`onFinish()`), and to process the command output (by overriding
|
| +`processOutputLine()`).
|
| +
|
| +## Examples
|
| +
|
| +In the most common case, a process_handler is created, then run followed by wait are called:
|
| +
|
| + proc_handler = ProcessHandler([cmd, args])
|
| + proc_handler.run(outputTimeout=60) # will time out after 60 seconds without output
|
| + proc_handler.wait()
|
| +
|
| +Often, the main thread will do other things:
|
| +
|
| + proc_handler = ProcessHandler([cmd, args])
|
| + proc_handler.run(timeout=60) # will time out after 60 seconds regardless of output
|
| + do_other_work()
|
| +
|
| + if proc_handler.proc.poll() is None:
|
| + proc_handler.wait()
|
| +
|
| +By default output is printed to stdout, but anything is possible:
|
| +
|
| + # this example writes output to both stderr and a file called 'output.log'
|
| + def some_func(line):
|
| + print >> sys.stderr, line
|
| +
|
| + with open('output.log', 'a') as log:
|
| + log.write('%s\n' % line)
|
| +
|
| + proc_handler = ProcessHandler([cmd, args], processOutputLine=some_func)
|
| + proc_handler.run()
|
| + proc_handler.wait()
|
| +
|
| +# TODO
|
| +
|
| +- Document improvements over `subprocess.Popen.kill`
|
| +- Introduce test the show improvements over `subprocess.Popen.kill`
|
|
|