Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: interruption signal not terminating the process when spamming <C-c> #478

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
42 changes: 32 additions & 10 deletions agentops/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from typing import Optional, List, Union
from uuid import UUID, uuid4
from datetime import datetime
import atexit
import signal

from .exceptions import ApiServerException
from .enums import EndState
Expand Down Expand Up @@ -71,6 +73,10 @@ def __init__(
self.stop_flag.set()
self.thread.join(timeout=1)

self._cleanup_done = False
atexit.register(self._cleanup)
signal.signal(signal.SIGINT, self._signal_handler)

def set_video(self, video: str) -> None:
"""
Sets a url to the video recording of the session.
Expand All @@ -86,17 +92,15 @@ def end_session(
end_state_reason: Optional[str] = None,
video: Optional[str] = None,
) -> Union[Decimal, None]:
if not self.is_running:
return

if not any(end_state == state.value for state in EndState):
return logger.warning("Invalid end_state. Please use one of the EndState enums")
with self.lock:
if not self.is_running or self.end_timestamp:
return

self.end_timestamp = get_ISO_time()
self.end_state = end_state
self.end_state_reason = end_state_reason
if video is not None:
self.video = video
self.end_timestamp = get_ISO_time()
self.end_state = end_state
self.end_state_reason = end_state_reason
if video is not None:
self.video = video

self.stop_flag.set()
self.thread.join(timeout=1)
Expand Down Expand Up @@ -388,5 +392,23 @@ def wrapper(*args, **kwargs):

return wrapper

def _signal_handler(self, signum, frame):
"""Handle interrupt signals gracefully"""
self._cleanup()
# Re-raise the signal after cleanup
signal.signal(signum, signal.default_int_handler)
signal.raise_signal(signum)

def _cleanup(self):
"""Ensure clean shutdown of session"""
if not self._cleanup_done:
with self.lock:
if self.is_running and not self.end_timestamp:
self.end_session(
end_state="Indeterminate",
end_state_reason="Session interrupted",
)
self._cleanup_done = True


active_sessions: List[Session] = []
Loading