fix: start_server.py — исправлено завершение по Ctrl+C

Проблемы:
- signal_handler блокировал shutdown()
- Порт не освобождался после Ctrl+C
- Невозможно было перезапустить сервер

Решения:
- Убран signal_handler — используется KeyboardInterrupt
- shutdown() вызывается в отдельном потоке (avoid deadlock)
- with контекст для автоматического закрытия
- allow_reuse_address = True для быстрого рестарта
- Обработка OSError при занятом порте
This commit is contained in:
2026-05-21 13:19:59 +03:00
parent 0776d839b9
commit ed6ecc548b
+30 -29
View File
@@ -13,16 +13,13 @@ import argparse
import http.server
import socketserver
import os
import signal
import sys
import threading
from pathlib import Path
PORT = 8080
SCRIPT_DIR = Path(__file__).parent.resolve()
# Global server reference for cleanup
httpd = None
class CustomHandler(http.server.SimpleHTTPRequestHandler):
"""Custom handler with better logging."""
@@ -36,32 +33,20 @@ class CustomHandler(http.server.SimpleHTTPRequestHandler):
pass
def signal_handler(sig, frame):
"""Handle Ctrl+C gracefully."""
print("\n👋 Shutting down...")
if httpd:
# Use shutdown() to stop serve_forever()
httpd.shutdown()
class ReusableTCPServer(socketserver.TCPServer):
"""TCP Server with address reuse enabled."""
allow_reuse_address = True
def main():
global httpd
parser = argparse.ArgumentParser(description='WebSocket Client Web Server')
parser.add_argument('--port', type=int, default=PORT, help=f'Port (default: {PORT})')
parser.add_argument('--host', default='0.0.0.0', help='Host (default: 0.0.0.0)')
args = parser.parse_args()
# Change to websocket-service directory
# Change to script directory
os.chdir(SCRIPT_DIR)
# Register signal handlers
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# Allow socket reuse
socketserver.TCPServer.allow_reuse_address = True
print(f"""
╔══════════════════════════════════════════════════════════╗
║ 🛰️ Wyoming Satellite WebSocket Client Server ║
@@ -74,16 +59,32 @@ def main():
╚══════════════════════════════════════════════════════════╝
""")
httpd = socketserver.TCPServer((args.host, args.port), CustomHandler)
print(f"🚀 Server started on http://{args.host}:{args.port}")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
finally:
print("\n👋 Server stopped")
httpd.server_close()
with ReusableTCPServer((args.host, args.port), CustomHandler) as httpd:
print(f"🚀 Server started on http://{args.host}:{args.port}")
print("📖 Serving files from:", SCRIPT_DIR)
print("\n⌨️ Press Ctrl+C to stop\n")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\n👋 Shutting down gracefully...")
# Shutdown in a separate thread to avoid deadlock
shutdown_thread = threading.Thread(target=httpd.shutdown)
shutdown_thread.start()
shutdown_thread.join(timeout=2)
httpd.server_close()
print("✅ Server stopped successfully")
except OSError as e:
print(f"\n❌ Error: Could not bind to port {args.port}")
print(f" {e}")
print("\n💡 Try using a different port:")
print(f" python3 {sys.argv[0]} --port 8081\n")
sys.exit(1)
except Exception as e:
print(f"\n❌ Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":