58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
"""Private launch barrier for sdk.run_process; stdlib-only under Python -I."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import threading
|
|
import time
|
|
|
|
|
|
def watch_parent(expected: int):
|
|
while True:
|
|
if os.getppid() != expected:
|
|
os.killpg(os.getpid(), signal.SIGKILL)
|
|
time.sleep(0.1)
|
|
|
|
|
|
def main():
|
|
status = Path(sys.argv[1])
|
|
if os.name != "nt":
|
|
threading.Thread(target=watch_parent, args=(int(sys.argv[2]),), daemon=True).start()
|
|
# Until the parent owns our job/session and sends this line, no business
|
|
# process can start. Buffering is local; tool stdin uses a separate pipe.
|
|
control = sys.stdin.buffer.readline(1024 * 1024 + 1)
|
|
if not control.endswith(b"\n") or len(control) > 1024 * 1024:
|
|
return
|
|
request = json.loads(control)
|
|
size = request["input_size"]
|
|
if type(size) is not int or not 0 <= size <= 64 * 1024 * 1024:
|
|
return
|
|
content = sys.stdin.buffer.read(size) if request["has_input"] else None
|
|
if content is not None and len(content) != size:
|
|
return
|
|
try:
|
|
result = subprocess.run(
|
|
request["argv"],
|
|
shell=False,
|
|
stdin=None if request["has_input"] else subprocess.DEVNULL,
|
|
input=content,
|
|
creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
|
|
check=False,
|
|
)
|
|
response = {"returncode": result.returncode}
|
|
except OSError:
|
|
response = {"launch_failed": True}
|
|
pending = status.with_suffix(".tmp")
|
|
pending.write_text(json.dumps(response), encoding="utf-8")
|
|
pending.replace(status)
|
|
# Remain the session/group leader until the owner reclaims the whole tree.
|
|
while True:
|
|
time.sleep(60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|