Skip to content

Commit

Permalink
fix: Send C-c to stop background process when stop button is clicked
Browse files Browse the repository at this point in the history
When the stop button is clicked, it only changes the agent state but doesn't
actually stop the running process. This causes the process to continue running
in the background, preventing new commands from being executed.

This fix modifies the AgentController to send a C-c command to stop any running
process when transitioning to the STOPPED state. This ensures that background
processes are properly terminated when the stop button is clicked.

Added tests:
- test_bash_session_stop_behavior: Shows the issue with background processes
- test_bash_session_stop_command: Shows that C-c properly stops processes
- test_agent_controller_stop: Verifies the fix works correctly
  • Loading branch information
openhands-agent committed Feb 20, 2025
1 parent efd0a6e commit 5866e6c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
4 changes: 4 additions & 0 deletions openhands/controller/agent_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,10 @@ async def set_agent_state_to(self, new_state: AgentState) -> None:
# sync existing metrics BEFORE resetting the agent
await self.update_state_after_step()
self.state.metrics.merge(self.state.local_metrics)
# Send C-c to stop any running process
if self._pending_action is not None and isinstance(self._pending_action, CmdRunAction):
stop_action = CmdRunAction(command="C-c", is_input="true")
self.event_stream.add_event(stop_action, EventSource.AGENT)
self._reset()
elif (
new_state == AgentState.RUNNING
Expand Down
51 changes: 50 additions & 1 deletion tests/unit/test_bash_session_stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,53 @@ def test_bash_session_stop_command():
assert "test" in new_result.content

# Clean up
session.close()
session.close()

def test_agent_controller_stop():
"""Test that the agent controller sends C-c when stopping."""
from openhands.controller.agent_controller import AgentController
from openhands.controller.agent import Agent
from openhands.core.schema import AgentState
from openhands.events import EventStream
from openhands.llm.llm import LLM
from openhands.core.config import AppConfig, LLMConfig, AgentConfig

# Create a mock event stream to capture events
from openhands.storage.local import LocalFileStore
file_store = LocalFileStore("/tmp")
event_stream = EventStream(sid="test", file_store=file_store)
events = []
def on_event(event):
events.append(event)
event_stream.subscribe("test", on_event, "test")

# Create a mock agent
class MockAgent(Agent):
def step(self, history):
return None

# Create a mock agent controller
llm = LLM(config=LLMConfig())
agent = MockAgent(llm=llm, config=AgentConfig())
controller = AgentController(
agent=agent,
event_stream=event_stream,
max_iterations=10,
agent_configs={},
agent_to_llm_config={},
sid="test",
confirmation_mode=False,
headless_mode=True,
)

# Set up a pending action
pending_action = CmdRunAction(command="sleep 10")
controller._pending_action = pending_action

# Change state to STOPPED
import asyncio
asyncio.get_event_loop().run_until_complete(controller.set_agent_state_to(AgentState.STOPPED))

# Verify that C-c was sent
stop_events = [e for e in events if isinstance(e, CmdRunAction) and e.command == "C-c" and e.is_input == "true"]
assert len(stop_events) == 1, "Expected exactly one C-c command to be sent"

0 comments on commit 5866e6c

Please sign in to comment.