Skip to content

Commit f239d5c

Browse files
fix: resolve agent termination issue by properly cleaning up telemetry system
- Add proper cleanup in Agent.start() and Agent.astart() methods using try-finally blocks - Implement _cleanup_telemetry() method to ensure telemetry system shutdown - Prevent hanging after agent execution by properly shutting down background threads - Add test files to verify the termination fix works correctly Fixes #987 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 63286ff commit f239d5c

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

simple_test.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Simple test to verify the termination fix
4+
"""
5+
import sys
6+
import os
7+
8+
# Add the src directory to the path so we can import praisonaiagents
9+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
10+
11+
print("Testing agent termination fix...")
12+
13+
try:
14+
from praisonaiagents import Agent
15+
16+
# Create agent with minimal setup
17+
agent = Agent(instructions="You are a helpful AI assistant")
18+
19+
# Run the same test as in the issue
20+
print("Running agent.start() ...")
21+
response = agent.start("Write a movie script about a robot on Mars")
22+
23+
print("Agent completed successfully!")
24+
print(f"Response type: {type(response)}")
25+
print(f"Response length: {len(str(response)) if response else 'None'}")
26+
27+
# If we get here, the fix worked
28+
print("SUCCESS: Program should terminate properly!")
29+
30+
except Exception as e:
31+
print(f"ERROR: Exception occurred: {e}")
32+
import traceback
33+
traceback.print_exc()
34+
sys.exit(1)
35+
36+
print("Test completed - program should exit now.")

src/praisonai-agents/praisonaiagents/agent/agent.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,15 +1929,39 @@ async def _achat_completion(self, response, tools, reasoning_steps=False):
19291929

19301930
async def astart(self, prompt: str, **kwargs):
19311931
"""Async version of start method"""
1932-
return await self.achat(prompt, **kwargs)
1932+
try:
1933+
result = await self.achat(prompt, **kwargs)
1934+
return result
1935+
finally:
1936+
# Ensure proper cleanup of telemetry system to prevent hanging
1937+
self._cleanup_telemetry()
19331938

19341939
def run(self):
19351940
"""Alias for start() method"""
19361941
return self.start()
19371942

1943+
def _cleanup_telemetry(self):
1944+
"""Clean up telemetry system to ensure proper program termination."""
1945+
try:
1946+
# Import here to avoid circular imports
1947+
from ..telemetry import get_telemetry
1948+
1949+
# Get the global telemetry instance and shut it down
1950+
telemetry = get_telemetry()
1951+
if telemetry and hasattr(telemetry, 'shutdown'):
1952+
telemetry.shutdown()
1953+
except Exception as e:
1954+
# Log error but don't fail the execution
1955+
logging.debug(f"Error cleaning up telemetry: {e}")
1956+
19381957
def start(self, prompt: str, **kwargs):
19391958
"""Start the agent with a prompt. This is a convenience method that wraps chat()."""
1940-
return self.chat(prompt, **kwargs)
1959+
try:
1960+
result = self.chat(prompt, **kwargs)
1961+
return result
1962+
finally:
1963+
# Ensure proper cleanup of telemetry system to prevent hanging
1964+
self._cleanup_telemetry()
19411965

19421966
def execute(self, task, context=None):
19431967
"""Execute a task synchronously - backward compatibility method"""

test_fix.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Test script to verify the termination fix works
4+
"""
5+
import sys
6+
import os
7+
import signal
8+
import time
9+
from threading import Timer
10+
11+
# Add the src directory to the path so we can import praisonaiagents
12+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
13+
14+
# Set up timeout mechanism
15+
def timeout_handler(signum, frame):
16+
print("ERROR: Test timed out - program is still hanging!")
17+
sys.exit(1)
18+
19+
# Set up signal handler for timeout
20+
signal.signal(signal.SIGALRM, timeout_handler)
21+
signal.alarm(30) # 30 second timeout
22+
23+
try:
24+
# Import here to avoid issues with path setup
25+
from praisonaiagents import Agent
26+
27+
print("Testing agent termination fix...")
28+
29+
# Create agent with minimal setup
30+
agent = Agent(instructions="You are a helpful AI assistant")
31+
32+
# Run the same test as in the issue
33+
print("Running agent.start() ...")
34+
response = agent.start("Write a short hello world message")
35+
36+
print(f"Agent completed successfully!")
37+
print(f"Response (truncated): {str(response)[:100]}...")
38+
39+
# If we get here, the fix worked
40+
print("SUCCESS: Program terminated properly without hanging!")
41+
42+
except Exception as e:
43+
print(f"ERROR: Exception occurred: {e}")
44+
import traceback
45+
traceback.print_exc()
46+
sys.exit(1)
47+
finally:
48+
# Cancel the alarm
49+
signal.alarm(0)

test_termination_issue.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
Test script to reproduce the termination issue
3+
"""
4+
import sys
5+
import os
6+
7+
# Add the src directory to the path so we can import praisonaiagents
8+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src', 'praisonai-agents'))
9+
10+
from praisonaiagents import Agent
11+
12+
def test_termination():
13+
"""Test that the agent terminates properly after execution"""
14+
print("Testing agent termination...")
15+
16+
agent = Agent(instructions="You are a helpful AI assistant")
17+
response = agent.start("Write a short hello world message")
18+
19+
print(f"Agent response: {response}")
20+
print("Agent execution completed. Testing if program terminates...")
21+
22+
# If this completes without hanging, the fix works
23+
return True
24+
25+
if __name__ == "__main__":
26+
result = test_termination()
27+
if result:
28+
print("SUCCESS: Program terminated properly")
29+
else:
30+
print("FAILURE: Program did not terminate")

0 commit comments

Comments
 (0)