Spaces:
Sleeping
Sleeping
| """Persistent server starter: spawns server with proper detachment on Windows. | |
| Uses subprocess.Popen with DETACHED_PROCESS + CREATE_NEW_PROCESS_GROUP flags | |
| so the child survives parent exit. The child's stdio is redirected to log files. | |
| """ | |
| import os | |
| import sys | |
| import subprocess | |
| import time | |
| import urllib.request | |
| WORKDIR = r"D:\opencode\captcha-solver-api" | |
| LOG_DIR = r"D:\opencode\logs" | |
| PYTHON = r"C:\Users\Administrator\AppData\Local\Programs\Python\Python312\python.exe" | |
| PORT = 8765 | |
| # Ensure log dir | |
| os.makedirs(LOG_DIR, exist_ok=True) | |
| log_path = os.path.join(LOG_DIR, "solver.log") | |
| err_path = os.path.join(LOG_DIR, "solver.err") | |
| # Kill existing | |
| subprocess.run( | |
| ["taskkill", "/F", "/IM", "python.exe", "/FI", f"WindowTitle eq captcha*"], | |
| capture_output=True | |
| ) | |
| time.sleep(1) | |
| # Brute force kill anything on the port | |
| out = subprocess.run( | |
| ["netstat", "-ano"], | |
| capture_output=True, text=True | |
| ) | |
| for line in out.stdout.splitlines(): | |
| if f":{PORT}" in line and "LISTENING" in line: | |
| parts = line.split() | |
| if parts: | |
| try: | |
| pid = int(parts[-1]) | |
| print(f"killing PID {pid} on port {PORT}") | |
| subprocess.run(["taskkill", "/F", "/PID", str(pid)], capture_output=True) | |
| except (ValueError, IndexError): | |
| pass | |
| # Spawn server fully detached | |
| log_f = open(log_path, "wb") | |
| err_f = open(err_path, "wb") | |
| # DETACHED_PROCESS = 0x00000008, CREATE_NEW_PROCESS_GROUP = 0x00000200 | |
| flags = 0x00000008 | 0x00000200 | |
| proc = subprocess.Popen( | |
| [PYTHON, "-u", "-m", "captcha_solver.main", "--port", str(PORT)], | |
| cwd=WORKDIR, | |
| stdout=log_f, | |
| stderr=err_f, | |
| stdin=subprocess.DEVNULL, | |
| creationflags=flags, | |
| close_fds=True, | |
| ) | |
| print(f"started PID {proc.pid}") | |
| # Wait for server to be ready | |
| print("waiting for server...") | |
| for i in range(60): | |
| time.sleep(1) | |
| try: | |
| with urllib.request.urlopen(f"http://localhost:{PORT}/health", timeout=2) as r: | |
| data = r.read().decode("utf-8") | |
| print(f"READY after {i+1}s") | |
| print(f"health: {data[:200]}") | |
| break | |
| except Exception: | |
| if i % 5 == 4: | |
| print(f" still waiting ({i+1}s)...") | |
| else: | |
| print("TIMEOUT after 60s") | |
| print("--- log ---") | |
| if os.path.exists(log_path): | |
| with open(log_path) as f: | |
| print(f.read()[-2000:]) | |
| print("--- err ---") | |
| if os.path.exists(err_path): | |
| with open(err_path) as f: | |
| print(f.read()[-2000:]) | |
| sys.exit(1) | |