def Spawn()

in tools/android/emulator/common.py [0:0]


def Spawn(args, proc_input=None, proc_output=None, exec_dir=None,
          exec_env=None, logfile=None, **kwargs):
  """Execs a subprocess using Popen.

  Task output will be logged to file.

  Args:
    args: A list of arguments to execute
    proc_input: takes true or a file descriptor. If true the stdin is a
      readable pipe. If file descriptor the file is piped into stdin
    proc_output: true for stdout/stderr to be pipes, file descriptor to pipe to
      file.
    exec_dir: the directory the subprocess will run from.
    exec_env: the environment the subprocess will use.
    logfile: an optional filename to log stdout/stderr.
    **kwargs: passed to subprocess.Popen as is.

  Returns:
    An object supporting Popen.wait(), Popen.stdout and Popen.stdin
  """
  proc_err = proc_output
  if not exec_dir:
    exec_dir = os.getcwd()
  if not exec_env:
    exec_env = dict(os.environ)

  if not logfile:
    logfile = CommandLogFile(args, exec_dir, exec_env)
  if not logfile:
    logfile = '/dev/null'

  logfile_handle = None

  if proc_input == True:  # could be a file or True or none
    proc_input = subprocess.PIPE

  logged_to_file = False
  if proc_output == True:  # could be a file or True or None
    proc_output = subprocess.PIPE
    proc_err = subprocess.PIPE
  elif not proc_output:
    # caller not doing anything with outputs, dont pass them on.
    # just write output straight to log.
    logged_to_file = True
    logfile_handle = open(logfile, 'a')
    proc_output = logfile_handle
    proc_err = logfile_handle

  logging.debug('Launching %s. input: %s, output: %s, execdir: %s',
                ' '.join(args), proc_input, proc_output, exec_dir)
  task = None

  if not logged_to_file:
    # launch the task and tee tasks to write the stdout/stderr to file and then
    # pass it along to the caller's pipes or files.
    task = subprocess.Popen(args, stdout=subprocess.PIPE, stdin=proc_input,
                            env=exec_env, cwd=exec_dir, stderr=subprocess.PIPE,
                            close_fds=True,
                            **kwargs)
    log_out_task = subprocess.Popen(_GetLogCommand(logfile),
                                    stdin=task.stdout, stdout=proc_output,
                                    stderr=open('/dev/null'),
                                    close_fds=True)
    log_err_task = subprocess.Popen(_GetLogCommand(logfile, is_stderr=True),
                                    stdin=task.stderr, stdout=proc_err,
                                    stderr=open('/dev/null'),
                                    close_fds=True)

    task.stdout = log_out_task.stdout
    task.stderr = log_err_task.stdout
    task.tee_stdout_task = log_out_task
    task.tee_stderr_task = log_err_task
  else:
    # proc_output and proc_error are already pointing to the logfiles.
    task = subprocess.Popen(args, stdout=proc_output, stdin=proc_input,
                            env=exec_env, cwd=exec_dir, stderr=proc_err,
                            close_fds=True)
    task.logfile_handle = logfile_handle

  task.logged_stdout = ''
  task.logged_stderr = ''
  task.spawn_env = exec_env

  def LoggingCommunicate(task_in=None):
    """Used to capture the results of a call to communicate.

    Args:
      task_in: optional input to communicate
    Returns:
      A pair of (stdout, stderr) from the process.
    """
    task.logged_stdout, task.logged_stderr = task.RawCommunicate(input=task_in)
    return (task.logged_stdout, task.logged_stderr)

  task.RawCommunicate = task.communicate
  task.communicate = LoggingCommunicate

  return task