fix: GFK client Windows compatibility - replace pkill with taskkill

- Replace Linux-only 'pkill' command with cross-platform solution
- Use 'wmic' and 'taskkill' on Windows to kill existing Python processes
- Add CREATE_NEW_PROCESS_GROUP for proper signal handling on Windows
- Improve shutdown handling for both platforms

Fixes FileNotFoundError: [WinError 2] when starting GFK on Windows.
This commit is contained in:
SamNet-dev
2026-02-04 04:50:28 -06:00
parent 4009ba4bd2
commit 5ca4d22cdf

View File

@@ -3,36 +3,82 @@ import os
import time import time
import sys import sys
import signal import signal
import platform
IS_WINDOWS = platform.system() == 'Windows'
scripts = ['quic_client.py', 'vio_client.py'] scripts = ['quic_client.py', 'vio_client.py']
def kill_existing_script(script_name):
"""Kill any existing instance of the script (cross-platform)"""
if IS_WINDOWS:
# On Windows, use taskkill to find and kill python processes
try:
result = subprocess.run(
['wmic', 'process', 'where',
f"commandline like '%{script_name}%' and name like '%python%'",
'get', 'processid'],
capture_output=True, text=True, stderr=subprocess.DEVNULL
)
for line in result.stdout.split('\n'):
line = line.strip()
if line.isdigit():
subprocess.run(['taskkill', '/F', '/PID', line],
stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
except Exception:
pass
else:
subprocess.run(['pkill', '-f', script_name], stderr=subprocess.DEVNULL)
def run_script(script_name): def run_script(script_name):
# Use sys.executable to run with the same Python interpreter (venv) """Start a script, killing any existing instance first"""
subprocess.run(['pkill', '-f', script_name], stderr=subprocess.DEVNULL) kill_existing_script(script_name)
time.sleep(0.5) time.sleep(0.5)
p = subprocess.Popen([sys.executable, script_name])
if IS_WINDOWS:
p = subprocess.Popen([sys.executable, script_name],
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
else:
p = subprocess.Popen([sys.executable, script_name])
return p return p
processes = [] processes = []
def signal_handler(sig, frame):
print('You pressed Ctrl+C!')
for p in processes:
print("terminated:",p)
p.terminate()
def signal_handler(sig, frame):
print('\nShutting down GFK client...')
for p in processes:
try:
p.terminate()
p.wait(timeout=3)
except Exception:
try:
p.kill()
except Exception:
pass
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":
signal.signal(signal.SIGINT, signal_handler)
if not IS_WINDOWS:
signal.signal(signal.SIGTERM, signal_handler)
print("Starting GFK client...")
p1 = run_script(scripts[0]) p1 = run_script(scripts[0])
time.sleep(1) time.sleep(1)
p2 = run_script(scripts[1]) p2 = run_script(scripts[1])
processes.extend([p1, p2]) # Modify global list, don't shadow it processes.extend([p1, p2])
signal.signal(signal.SIGINT, signal_handler)
p1.wait() print("GFK running. Press Ctrl+C to stop.\n")
p2.wait()
print("All subprocesses have completed.") try:
p1.wait()
p2.wait()
print("All subprocesses have completed.")
except KeyboardInterrupt:
signal_handler(None, None)