Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion concore.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
import re
import zmq
import numpy as np
import atexit
import signal

logging.basicConfig(
level=logging.INFO,
format='%(levelname)s - %(message)s'
Expand Down Expand Up @@ -72,6 +75,7 @@ def recv_json_with_retry(self):

# Global ZeroMQ ports registry
zmq_ports = {}
_cleanup_in_progress = False

def init_zmq_port(port_name, port_type, address, socket_type_str):
"""
Expand All @@ -98,12 +102,45 @@ def init_zmq_port(port_name, port_type, address, socket_type_str):
logging.error(f"An unexpected error occurred during ZMQ port initialization for {port_name}: {e}")

def terminate_zmq():
for port in zmq_ports.values():
"""Clean up all ZMQ sockets and contexts before exit."""
global _cleanup_in_progress

if _cleanup_in_progress:
return # Already cleaning up, prevent reentrant calls

if not zmq_ports:
return # No ports to clean up

_cleanup_in_progress = True
print("\nCleaning up ZMQ resources...")
for port_name, port in zmq_ports.items():
try:
port.socket.close()
port.context.term()
print(f"Closed ZMQ port: {port_name}")
except Exception as e:
logging.error(f"Error while terminating ZMQ port {port.address}: {e}")
zmq_ports.clear()
_cleanup_in_progress = False

def signal_handler(sig, frame):
"""Handle interrupt signals gracefully."""
print(f"\nReceived signal {sig}, shutting down gracefully...")
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signal_handler calls sys.exit(0) which will trigger the atexit handler, resulting in terminate_zmq() being called twice. While the code guards against double cleanup with the 'if not zmq_ports' check, this creates unnecessary overhead and potential confusion. Consider either: (1) not calling sys.exit(0) in the signal handler and instead just returning, allowing the program to exit naturally and trigger atexit, or (2) unregistering the atexit handler before calling sys.exit in the signal handler using atexit.unregister(terminate_zmq).

Suggested change
print(f"\nReceived signal {sig}, shutting down gracefully...")
print(f"\nReceived signal {sig}, shutting down gracefully...")
# Prevent terminate_zmq from being called twice: once here and once via atexit
try:
atexit.unregister(terminate_zmq)
except Exception:
# If unregister fails for any reason, proceed with explicit cleanup anyway
pass

Copilot uses AI. Check for mistakes.
# Prevent terminate_zmq from being called twice: once here and once via atexit
try:
atexit.unregister(terminate_zmq)
except Exception:
# If unregister fails for any reason, proceed with explicit cleanup anyway
pass
terminate_zmq()
sys.exit(0)

# Register cleanup handlers
atexit.register(terminate_zmq)
signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl+C
if not hasattr(sys, 'getwindowsversion'):
signal.signal(signal.SIGTERM, signal_handler) # Handle termination (Unix only)

# --- ZeroMQ Integration End ---


Expand Down