def communicate_teeing_stdout_and_stderr(self, stdin=None):
    """
    Just like subprocess.communicate, but tees stdout and stderr to both sys.std{out,err} and a
    buffer. Only operates on stdout/stderr if the Popen call send them to subprocess.PIPE.
    :param stdin: A string to send to the stdin of the subprocess.
    :return: (stdout, stderr) as strings.
    """
    if stdin is not None and self._process.stdin is not None:
      self._process.stdin.write(stdin)

    def fork_tee(infile, outfile):
      if infile is None:
        return lambda: None

      queue = multiprocessing.Queue()
      process = multiprocessing.Process(target=_tee, args=(infile, outfile, queue.put))
      process.start()
      def join_and_get_output():
        process.join()
        return queue.get()
      return join_and_get_output

    stdout = fork_tee(self._process.stdout, sys.stdout)
    stderr = fork_tee(self._process.stderr, sys.stderr)

    self._process.wait()

    return stdout(), stderr()
Just like subprocess.communicate, but tees stdout and stderr to both sys.std{out,err} and a
    buffer. Only operates on stdout/stderr if the Popen call send them to subprocess.PIPE.
    :param stdin: A string to send to the stdin of the subprocess.
    :return: (stdout, stderr) as strings.