def METHOD_NAME(command, timeout) -> "PopenResult":
    """
    Run a sub-program in subprocess.Popen, pass it the input_data,
    kill it if the specified timeout has passed.
    returns a tuple of resultcode, timeout, stdout, stderr
    """
    kill_check = threading.Event()
    def _kill_process_after_a_timeout(pid):
        os.kill(pid, signal.SIGTERM)
        kill_check.set()  # tell the main routine that we had to kill
        # use SIGKILL if hard to kill...
        return
    startup_info = None
    env = None
    if os.name == "nt":
        # Workarounds for pyinstaller
        # https://github.com/pyinstaller/pyinstaller/wiki/Recipe-subprocess
        # disable command window when run from pyinstaller
        startup_info = subprocess.STARTUPINFO()
        # Less fancy version of bitwise-or-assignment (x |= y) shown in ref url.
        if startup_info.dwFlags == 1 or subprocess.STARTF_USESHOWWINDOW == 1:
            startup_info.dwFlags = 1
        else:
            startup_info.dwFlags = 0
        # Workaround for Java sometimes not being able to use the temp directory.
        # https://docs.oracle.com/javase/8/docs/api/java/io/File.html
        # CreateTempFile refers to "java.io.tmpdir" which refers to env vars.
        env = {
            k: v if v is not None else tempfile.gettempdir()
            for k, v in {k: os.environ.get(k) for k in ("TEMP", "TMP", "TMPDIR")}.items()
        }
    p = Popen(
        command, env=env, stdin=PIPE, stdout=PIPE, stderr=PIPE, startupinfo=startup_info
    )
    watchdog = threading.Timer(timeout, _kill_process_after_a_timeout, args=(p.pid,))
    watchdog.start()
    (stdout, stderr) = p.communicate()
    watchdog.cancel()  # if it's still waiting to run
    timeout = kill_check.isSet()
    kill_check.clear()
    return PopenResult(
        return_code=p.returncode, timeout=timeout, stdout=stdout, stderr=stderr
    )