def Exec(cmd, env=None, timeout=0, waitfor=0):
  if isinstance(cmd, basestring):
    shell = True
  else:
    shell = False

  if env:
    environ = os.environ.copy()
    environ.update(env)
    env = environ

  p = subprocess.Popen(
      cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell)

  if timeout <= 0:
    stdout, stderr = p.communicate()
  else:
    inactive = 0
    stdout = []
    stderr = []

    SetFileNonBlocking(p.stdout)
    SetFileNonBlocking(p.stderr)

    returncode = None

    while returncode is None:
      rlist, _, _ = select.select([p.stdout, p.stderr], [], [], 1.0)

      if not rlist:
        inactive += 1
        if inactive >= timeout:
          logging.error('cmd has timed out: %s', cmd)
          logging.error('Sending SIGTERM to PID=%s', p.pid)
          os.kill(p.pid, signal.SIGTERM)
          break  # note: this is a hard timeout, we don't read() again
      else:
        inactive = 0
        for fd in rlist:
          if fd is p.stdout:
            stdout.append(fd.read())
          elif fd is p.stderr:
            stderr.append(fd.read())

      returncode = p.poll()

    # if the process was just killed, wait for waitfor seconds.
    if inactive >= timeout and waitfor > 0:
      time.sleep(waitfor)
    # attempt to obtain returncode one last chance
    returncode = p.poll()
    stdout = ''.join(stdout)
    stderr = ''.join(stderr)

  return p.returncode, stdout, stderr
Called on receipt of the result header.
dataset/ETHPy150Open google/simian/src/simian/mac/client/flight_common.py/Exec--crossover with--dataset/ETHPy150Open nigelsmall/py2neo/py2neo/database/__init__.py/BoltDataSource.on_header