331 lines
12 KiB
Python
331 lines
12 KiB
Python
"""
|
|
Kill Stale Processes
|
|
|
|
This script identifies and kills stale Python processes that might be causing
|
|
the dashboard startup freeze. It looks for:
|
|
1. Hanging dashboard processes
|
|
2. Stale COB data collection threads
|
|
3. Matplotlib GUI processes
|
|
4. Blocked network connections
|
|
|
|
Usage:
|
|
python kill_stale_processes.py
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import psutil
|
|
import signal
|
|
import time
|
|
from datetime import datetime
|
|
|
|
def find_python_processes():
|
|
"""Find all Python processes"""
|
|
python_processes = []
|
|
|
|
try:
|
|
for proc in psutil.process_iter(['pid', 'name', 'cmdline', 'create_time', 'status']):
|
|
try:
|
|
if proc.info['name'] and 'python' in proc.info['name'].lower():
|
|
# Get command line to identify dashboard processes
|
|
cmdline = ' '.join(proc.info['cmdline']) if proc.info['cmdline'] else ''
|
|
|
|
python_processes.append({
|
|
'pid': proc.info['pid'],
|
|
'name': proc.info['name'],
|
|
'cmdline': cmdline,
|
|
'create_time': proc.info['create_time'],
|
|
'status': proc.info['status'],
|
|
'process': proc
|
|
})
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
continue
|
|
|
|
except Exception as e:
|
|
print(f"Error finding Python processes: {e}")
|
|
|
|
return python_processes
|
|
|
|
def identify_dashboard_processes(python_processes):
|
|
"""Identify processes related to the dashboard"""
|
|
dashboard_processes = []
|
|
|
|
dashboard_keywords = [
|
|
'clean_dashboard',
|
|
'run_clean_dashboard',
|
|
'dashboard',
|
|
'trading',
|
|
'cob_data',
|
|
'orchestrator',
|
|
'data_provider'
|
|
]
|
|
|
|
for proc_info in python_processes:
|
|
cmdline = proc_info['cmdline'].lower()
|
|
|
|
# Check if this is a dashboard-related process
|
|
is_dashboard = any(keyword in cmdline for keyword in dashboard_keywords)
|
|
|
|
if is_dashboard:
|
|
dashboard_processes.append(proc_info)
|
|
|
|
return dashboard_processes
|
|
|
|
def identify_stale_processes(python_processes):
|
|
"""Identify potentially stale processes"""
|
|
stale_processes = []
|
|
current_time = time.time()
|
|
|
|
for proc_info in python_processes:
|
|
try:
|
|
proc = proc_info['process']
|
|
|
|
# Check if process is in a problematic state
|
|
if proc_info['status'] in ['zombie', 'stopped']:
|
|
stale_processes.append({
|
|
**proc_info,
|
|
'reason': f"Process status: {proc_info['status']}"
|
|
})
|
|
continue
|
|
|
|
# Check if process has been running for a very long time without activity
|
|
age_hours = (current_time - proc_info['create_time']) / 3600
|
|
if age_hours > 24: # Running for more than 24 hours
|
|
try:
|
|
# Check CPU usage
|
|
cpu_percent = proc.cpu_percent(interval=1)
|
|
if cpu_percent < 0.1: # Very low CPU usage
|
|
stale_processes.append({
|
|
**proc_info,
|
|
'reason': f"Old process ({age_hours:.1f}h) with low CPU usage ({cpu_percent:.1f}%)"
|
|
})
|
|
except:
|
|
pass
|
|
|
|
# Check for processes with high memory usage but no activity
|
|
try:
|
|
memory_info = proc.memory_info()
|
|
memory_mb = memory_info.rss / 1024 / 1024
|
|
|
|
if memory_mb > 500: # More than 500MB
|
|
cpu_percent = proc.cpu_percent(interval=1)
|
|
if cpu_percent < 0.1:
|
|
stale_processes.append({
|
|
**proc_info,
|
|
'reason': f"High memory usage ({memory_mb:.1f}MB) with low CPU usage ({cpu_percent:.1f}%)"
|
|
})
|
|
except:
|
|
pass
|
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
continue
|
|
|
|
return stale_processes
|
|
|
|
def kill_process_safely(proc_info, force=False):
|
|
"""Kill a process safely"""
|
|
try:
|
|
proc = proc_info['process']
|
|
pid = proc_info['pid']
|
|
|
|
print(f"Attempting to {'force kill' if force else 'terminate'} PID {pid}: {proc_info['name']}")
|
|
|
|
if force:
|
|
# Force kill
|
|
if os.name == 'nt': # Windows
|
|
os.system(f"taskkill /F /PID {pid}")
|
|
else: # Unix/Linux
|
|
os.kill(pid, signal.SIGKILL)
|
|
else:
|
|
# Graceful termination
|
|
proc.terminate()
|
|
|
|
# Wait for termination
|
|
try:
|
|
proc.wait(timeout=5)
|
|
print(f"✅ Process {pid} terminated gracefully")
|
|
return True
|
|
except psutil.TimeoutExpired:
|
|
print(f"⚠️ Process {pid} didn't terminate gracefully, will force kill")
|
|
return False
|
|
|
|
print(f"✅ Process {pid} killed")
|
|
return True
|
|
|
|
except (psutil.NoSuchProcess, psutil.AccessDenied) as e:
|
|
print(f"⚠️ Could not kill process {proc_info['pid']}: {e}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"❌ Error killing process {proc_info['pid']}: {e}")
|
|
return False
|
|
|
|
def check_port_usage():
|
|
"""Check if dashboard port is in use"""
|
|
try:
|
|
import socket
|
|
|
|
# Check if port 8050 is in use
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
result = sock.connect_ex(('localhost', 8050))
|
|
sock.close()
|
|
|
|
if result == 0:
|
|
print("⚠️ Port 8050 is in use")
|
|
|
|
# Find process using the port
|
|
for conn in psutil.net_connections():
|
|
if conn.laddr.port == 8050:
|
|
try:
|
|
proc = psutil.Process(conn.pid)
|
|
print(f" Port 8050 used by PID {conn.pid}: {proc.name()}")
|
|
return conn.pid
|
|
except:
|
|
pass
|
|
else:
|
|
print("✅ Port 8050 is available")
|
|
return None
|
|
|
|
except Exception as e:
|
|
print(f"Error checking port usage: {e}")
|
|
return None
|
|
|
|
def main():
|
|
"""Main function"""
|
|
print("🔍 Stale Process Killer")
|
|
print("=" * 50)
|
|
|
|
try:
|
|
# Step 1: Find all Python processes
|
|
print("🔍 Finding Python processes...")
|
|
python_processes = find_python_processes()
|
|
print(f"Found {len(python_processes)} Python processes")
|
|
|
|
# Step 2: Identify dashboard processes
|
|
print("\n🎯 Identifying dashboard processes...")
|
|
dashboard_processes = identify_dashboard_processes(python_processes)
|
|
|
|
if dashboard_processes:
|
|
print(f"Found {len(dashboard_processes)} dashboard-related processes:")
|
|
for proc in dashboard_processes:
|
|
age_hours = (time.time() - proc['create_time']) / 3600
|
|
print(f" PID {proc['pid']}: {proc['name']} (age: {age_hours:.1f}h, status: {proc['status']})")
|
|
print(f" Command: {proc['cmdline'][:100]}...")
|
|
else:
|
|
print("No dashboard processes found")
|
|
|
|
# Step 3: Check port usage
|
|
print("\n🌐 Checking port usage...")
|
|
port_pid = check_port_usage()
|
|
|
|
# Step 4: Identify stale processes
|
|
print("\n🕵️ Identifying stale processes...")
|
|
stale_processes = identify_stale_processes(python_processes)
|
|
|
|
if stale_processes:
|
|
print(f"Found {len(stale_processes)} potentially stale processes:")
|
|
for proc in stale_processes:
|
|
print(f" PID {proc['pid']}: {proc['name']} - {proc['reason']}")
|
|
else:
|
|
print("No stale processes identified")
|
|
|
|
# Step 5: Ask user what to do
|
|
if dashboard_processes or stale_processes or port_pid:
|
|
print("\n🤔 What would you like to do?")
|
|
print("1. Kill all dashboard processes")
|
|
print("2. Kill only stale processes")
|
|
print("3. Kill process using port 8050")
|
|
print("4. Kill all identified processes")
|
|
print("5. Show process details and exit")
|
|
print("6. Exit without killing anything")
|
|
|
|
try:
|
|
choice = input("\nEnter your choice (1-6): ").strip()
|
|
|
|
if choice == '1':
|
|
# Kill dashboard processes
|
|
print("\n🔫 Killing dashboard processes...")
|
|
for proc in dashboard_processes:
|
|
if not kill_process_safely(proc):
|
|
kill_process_safely(proc, force=True)
|
|
|
|
elif choice == '2':
|
|
# Kill stale processes
|
|
print("\n🔫 Killing stale processes...")
|
|
for proc in stale_processes:
|
|
if not kill_process_safely(proc):
|
|
kill_process_safely(proc, force=True)
|
|
|
|
elif choice == '3':
|
|
# Kill process using port 8050
|
|
if port_pid:
|
|
print(f"\n🔫 Killing process using port 8050 (PID {port_pid})...")
|
|
try:
|
|
proc = psutil.Process(port_pid)
|
|
proc_info = {
|
|
'pid': port_pid,
|
|
'name': proc.name(),
|
|
'process': proc
|
|
}
|
|
if not kill_process_safely(proc_info):
|
|
kill_process_safely(proc_info, force=True)
|
|
except:
|
|
print(f"❌ Could not kill process {port_pid}")
|
|
else:
|
|
print("No process found using port 8050")
|
|
|
|
elif choice == '4':
|
|
# Kill all identified processes
|
|
print("\n🔫 Killing all identified processes...")
|
|
all_processes = dashboard_processes + stale_processes
|
|
if port_pid:
|
|
try:
|
|
proc = psutil.Process(port_pid)
|
|
all_processes.append({
|
|
'pid': port_pid,
|
|
'name': proc.name(),
|
|
'process': proc
|
|
})
|
|
except:
|
|
pass
|
|
|
|
for proc in all_processes:
|
|
if not kill_process_safely(proc):
|
|
kill_process_safely(proc, force=True)
|
|
|
|
elif choice == '5':
|
|
# Show details
|
|
print("\n📋 Process Details:")
|
|
all_processes = dashboard_processes + stale_processes
|
|
for proc in all_processes:
|
|
print(f"\nPID {proc['pid']}: {proc['name']}")
|
|
print(f" Status: {proc['status']}")
|
|
print(f" Command: {proc['cmdline']}")
|
|
print(f" Created: {datetime.fromtimestamp(proc['create_time'])}")
|
|
|
|
elif choice == '6':
|
|
print("👋 Exiting without killing processes")
|
|
|
|
else:
|
|
print("❌ Invalid choice")
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n👋 Cancelled by user")
|
|
else:
|
|
print("\n✅ No problematic processes found")
|
|
|
|
print("\n" + "=" * 50)
|
|
print("💡 After killing processes, you can try:")
|
|
print(" python run_lightweight_dashboard.py")
|
|
print(" or")
|
|
print(" python fix_startup_freeze.py")
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error in main function: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
success = main()
|
|
if not success:
|
|
sys.exit(1) |