Skip to content

Fix example tmux socket paths - #5494

Merged
malhotra5 merged 1 commit into
mainfrom
fix-example-tmux-tmpdir
Oct 5, 2026
Merged

malhotra5 merged 1 commit into
mainfrom
fix-example-tmux-tmpdir

Conversation

@malhotra5

@malhotra5 malhotra5 commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

HUMAN:

This is a CI fix and does not require manual QA


AGENT:

Why

The examples workflow can fail after tmux sockets became uniquely named per terminal pool. The existing test harness sets TMUX_TMPDIR to pytest's long per-test tmp_path; tmux then appends tmux-<uid>/<socket_name>, and the longer unique socket name can exceed Unix socket path limits.

Summary

  • Use a short per-example TMUX_TMPDIR under /tmp in tests/examples/test_examples.py.
  • Preserve per-example isolation for parallel example workers.
  • Keep the production tmux socket isolation behavior unchanged.

Issue Number

#4049

How to Test

Commands run:

uv run pre-commit run --files tests/examples/test_examples.py
uv run pytest tests/examples/test_examples.py -q
uv run python - <<'PY'
import os
import tempfile
from openhands.tools.terminal.impl import TerminalExecutor
from openhands.tools.terminal.definition import TerminalAction

with tempfile.TemporaryDirectory(prefix='oh-ex-', dir='/tmp') as tmux_tmpdir:
    os.environ['TMUX_TMPDIR'] = tmux_tmpdir
    executor = TerminalExecutor(working_dir='.')
    try:
        result = executor(TerminalAction(command='pwd'))
        data = result.model_dump()
        print('TMUX_TMPDIR:', tmux_tmpdir)
        print('returncode:', data.get('metadata', {}).get('exit_code'))
        print('observation keys:', sorted(data.keys()))
    finally:
        executor.close()
PY

Results:

  • Pre-commit passed: Ruff format, Ruff lint, pycodestyle, pyright, import dependency rules, and tool registration checks all passed.
  • uv run pytest tests/examples/test_examples.py -q passed in default mode: 1 passed, 70 skipped.
  • The tmux smoke test initialized TerminalExecutor with a short TMUX_TMPDIR such as /tmp/oh-ex-jk3oxtiv and returned returncode: 0.

I did not run the full --run-examples workflow locally because it exercises many LLM-backed examples and requires CI-provided model/runtime credentials. The focused smoke test covers the failing tmux initialization path from the release PR logs.

Video/Screenshots

N/A

Design Doc

N/A

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

This PR was created by an AI agent (OpenHands) on behalf of the user.

@malhotra5 can click here to continue refining the PR


🐳 Agent Server images for this PR — GHCR package, pull/run commands, and all pushed tags (click to expand)

• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python-slim amd64, arm64 python-node-runtime Link
python-minimal amd64, arm64 python-node-runtime Link
python amd64, arm64 python-node-runtime Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:3e901e4-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-3e901e4-python \
  ghcr.io/openhands/agent-server:3e901e4-python

All tags pushed for this build

ghcr.io/openhands/agent-server:3e901e4-golang-amd64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-golang-amd64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-golang-amd64
ghcr.io/openhands/agent-server:3e901e4-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:3e901e4-golang-arm64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-golang-arm64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-golang-arm64
ghcr.io/openhands/agent-server:3e901e4-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:3e901e4-java-amd64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-java-amd64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-java-amd64
ghcr.io/openhands/agent-server:3e901e4-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:3e901e4-java-arm64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-java-arm64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-java-arm64
ghcr.io/openhands/agent-server:3e901e4-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:3e901e4-python-amd64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-amd64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-amd64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-amd64
ghcr.io/openhands/agent-server:3e901e4-python-arm64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-arm64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-arm64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-arm64
ghcr.io/openhands/agent-server:3e901e4-python-minimal-amd64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-minimal-amd64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-minimal-amd64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-minimal-amd64
ghcr.io/openhands/agent-server:3e901e4-python-minimal-arm64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-minimal-arm64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-minimal-arm64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-minimal-arm64
ghcr.io/openhands/agent-server:3e901e4-python-slim-amd64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-slim-amd64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-slim-amd64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-slim-amd64
ghcr.io/openhands/agent-server:3e901e4-python-slim-arm64
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-slim-arm64
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-slim-arm64
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-slim-arm64
ghcr.io/openhands/agent-server:3e901e4-golang
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-golang
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-golang
ghcr.io/openhands/agent-server:3e901e4-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:3e901e4-java
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-java
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-java
ghcr.io/openhands/agent-server:3e901e4-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:3e901e4-python-minimal
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-minimal
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-minimal
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-minimal
ghcr.io/openhands/agent-server:3e901e4-python-slim
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python-slim
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python-slim
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime-slim
ghcr.io/openhands/agent-server:3e901e4-python
ghcr.io/openhands/agent-server:3e901e45d8d58833dd73785ea087dfdadaa959f1-python
ghcr.io/openhands/agent-server:fix-example-tmux-tmpdir-python
ghcr.io/openhands/agent-server:3e901e4-python-node-runtime

About Multi-Architecture Support

  • Each variant tag (e.g., 3e901e4-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 3e901e4-python-amd64) are also available if needed

Use a short per-example TMUX_TMPDIR so tmux socket names remain under Unix path limits while preserving test isolation.\n\nCo-authored-by: openhands <openhands@all-hands.dev>
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🧹 PR Artifact Cleanup Queued

The .pr/ directory reached main after merge. A cleanup PR has been opened or updated: #5482

@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result: ✅ PASSED

Action log

@malhotra5 malhotra5 added the test-examples Run all applicable "examples/" files. Expensive operation. label Oct 5, 2026 — with OpenHands AI
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🔄 Running Examples with openhands/claude-haiku-4-5-20251001

Generated: 2026-10-05 01:37:56 UTC

Example Status Duration Cost
01_standalone_sdk/02_custom_tools.py ✅ PASS 25.5s $0.03
01_standalone_sdk/03_activate_skill.py ✅ PASS 24.0s $0.03
01_standalone_sdk/05_use_llm_registry.py ✅ PASS 12.6s $0.01
01_standalone_sdk/07_mcp_integration.py ✅ PASS 34.8s $0.03
01_standalone_sdk/09_pause_example.py ✅ PASS 15.1s $0.01
01_standalone_sdk/10_persistence.py ✅ PASS 25.3s $0.02
01_standalone_sdk/11_async.py ✅ PASS 32.9s $0.04
01_standalone_sdk/12_custom_secrets.py ✅ PASS 13.7s $0.01
01_standalone_sdk/13_get_llm_metrics.py ✅ PASS 28.0s $0.03
01_standalone_sdk/14_context_condenser.py ✅ PASS 1m 41s $0.11
01_standalone_sdk/17_image_input.py ✅ PASS 22.3s $0.02
01_standalone_sdk/18_send_message_while_processing.py ✅ PASS 23.2s $0.01
01_standalone_sdk/19_llm_routing.py ✅ PASS 20.5s $0.02
01_standalone_sdk/20_stuck_detector.py ✅ PASS 21.1s $0.03
01_standalone_sdk/21_generate_extraneous_conversation_costs.py ✅ PASS 10.4s $0.00
01_standalone_sdk/22_anthropic_thinking.py ✅ PASS 19.9s $0.01
01_standalone_sdk/23_responses_reasoning.py ✅ PASS 43.3s $0.01
01_standalone_sdk/24_planning_agent_workflow.py ✅ PASS 3m 49s $0.28
01_standalone_sdk/25_agent_delegation.py ✅ PASS 1m 1s $0.06
01_standalone_sdk/26_custom_visualizer.py ✅ PASS 17.0s $0.02
01_standalone_sdk/28_ask_agent_example.py ✅ PASS 30.5s $0.03
01_standalone_sdk/29_llm_streaming.py ✅ PASS 40.0s $0.02
01_standalone_sdk/30_tom_agent.py ✅ PASS 11.7s $0.01
01_standalone_sdk/31_iterative_refinement.py ✅ PASS 1m 17s $0.08
01_standalone_sdk/32_configurable_security_policy.py ✅ PASS 23.0s $0.02
01_standalone_sdk/33_hooks/main.py ✅ PASS 39.7s $0.04
01_standalone_sdk/34_critic_example.py ✅ PASS 2m 4s $0.02
01_standalone_sdk/36_event_json_to_openai_messages.py ✅ PASS 10.9s $0.00
01_standalone_sdk/37_llm_profile_store/main.py ✅ PASS 9.3s $0.00
01_standalone_sdk/38_browser_session_recording.py ✅ PASS 44.0s $0.04
01_standalone_sdk/39_llm_fallback.py ✅ PASS 12.5s $0.01
01_standalone_sdk/40_acp_agent_example.py ✅ PASS 57.2s $0.41
01_standalone_sdk/41_task_tool_set.py ✅ PASS 25.7s $0.03
01_standalone_sdk/42_file_based_subagents.py ✅ PASS 43.5s $0.05
01_standalone_sdk/44_model_switching_in_convo.py ✅ PASS 10.1s $0.01
01_standalone_sdk/45_parallel_tool_execution.py ✅ PASS 2m 56s $0.46
01_standalone_sdk/46_agent_settings.py ✅ PASS 11.8s $0.00
01_standalone_sdk/47_defense_in_depth_security.py ✅ PASS 4.4s $0.00
01_standalone_sdk/48_conversation_fork.py ✅ PASS 20.1s $0.01
01_standalone_sdk/49_switch_llm_tool.py ✅ PASS 8.0s $0.04
01_standalone_sdk/50_async_cancellation.py ✅ PASS 14.0s $0.00
01_standalone_sdk/51_agent_hooks/main.py ✅ PASS 39.2s $0.05
01_standalone_sdk/52_dynamic_workflow.py ✅ PASS 4m 29s $0.16
01_standalone_sdk/53_client_defined_tools.py ✅ PASS 14.2s $0.01
01_standalone_sdk/54_goal_completion_loop.py ✅ PASS 26.3s $0.02
01_standalone_sdk/55_persistent_memory.py ✅ PASS 24.6s $0.02
01_standalone_sdk/56_structured_output.py ✅ PASS 44.2s $0.06
01_standalone_sdk/57_prompt_hooks/main.py ✅ PASS 16.1s $0.00
01_standalone_sdk/58_ask_oracle_tool/main.py ✅ PASS 15.3s $0.01
01_standalone_sdk/59_route_task_to_model.py ✅ PASS 9.4s $0.05
02_remote_agent_server/01_convo_with_local_agent_server.py ✅ PASS 34.9s $0.02
02_remote_agent_server/02_convo_with_docker_sandboxed_server.py ✅ PASS 57.0s $0.04
02_remote_agent_server/03_browser_use_with_docker_sandboxed_server.py ✅ PASS 1m 49s --
02_remote_agent_server/04_convo_with_api_sandboxed_server.py ✅ PASS 1m 36s $0.02
02_remote_agent_server/06_custom_tool/main.py ✅ PASS 5m 28s $0.05
02_remote_agent_server/07_convo_with_cloud_workspace.py ✅ PASS 41.4s $0.03
02_remote_agent_server/08_convo_with_apptainer_sandboxed_server.py ✅ PASS 3m 41s $0.02
02_remote_agent_server/09_acp_agent_with_remote_runtime.py ✅ PASS 1m 12s $0.43
02_remote_agent_server/10_cloud_workspace_share_credentials.py ✅ PASS 51.5s $0.00
02_remote_agent_server/11_conversation_fork.py ✅ PASS 43.9s $0.00
02_remote_agent_server/12_settings_and_secrets_api.py ✅ PASS 2m 23s $0.02
02_remote_agent_server/13_workspace_get_llm.py ✅ PASS 30.1s $0.01
02_remote_agent_server/14_client_defined_tools.py ✅ PASS 35.5s $0.02
02_remote_agent_server/15_openai_compatible_gateway.py ✅ PASS 18.5s $0.02
02_remote_agent_server/16_deferred_init.py ✅ PASS 24.6s $0.00
04_llm_specific_tools/01_gpt5_apply_patch_preset.py ✅ PASS 25.5s $0.03
04_llm_specific_tools/02_gemini_file_tools.py ✅ PASS 38.8s $0.08
05_skills_and_plugins/01_loading_agentskills/main.py ✅ PASS 18.2s $0.02
05_skills_and_plugins/02_loading_plugins/main.py ✅ PASS 22.3s $0.03
05_skills_and_plugins/04_mixed_marketplace_skills/main.py ✅ PASS 4.5s $0.00

✅ All tests passed!

Total: 70 | Passed: 70 | Failed: 0 | Total Cost: $3.30

View full workflow run

@malhotra5
malhotra5 marked this pull request as ready for review October 5, 2026 02:09
@malhotra5
malhotra5 enabled auto-merge (squash) October 5, 2026 02:29

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This review was posted by an AI agent (OpenHands).

Review: Fix example tmux socket paths

Scope. Test-only CI harness change in tests/examples/test_examples.py. It belongs in this repository (the examples workflow and its harness are owned here) and the product/architecture direction is unchanged; production tmux socket isolation is untouched.

Root cause verified. The old harness set TMUX_TMPDIR to pytest's long per-test tmp_path. tmux resolves its socket as <TMUX_TMPDIR>/tmux-<uid>/<socket_name>, and the unique socket names (openhands-<uuid4().hex>) push the combined path past the Unix sun_path limit. I reproduced this directly with tmux 3.5a:

  • long pytest-style dir: path length 159 -> error connecting to ... (File name too long)
  • short /tmp/oh-ex-... dir: path length 71 -> rc=0

The change to tempfile.TemporaryDirectory(prefix="oh-ex-", dir="/tmp") keeps each example's socket dir short and still unique per test invocation, so parallel -n 4 workers stay isolated. Cleanup is handled by the context manager, which is strictly better than the mkdtemp approach suggested in #4049 (no leaked directories). The subprocess call and all result handling remain inside the with block, and stdout/stderr/returncode are assigned on both the success and TimeoutExpired paths, so no downstream reference is left unbound.

Verification. The test-examples workflow on the exact head 3e901e4 completed with all 70 examples passing (Run Examples Scripts, run 37250898290). The full head check set is green, including windows-tests, pre-commit, tools-tests, and agent-server-tests. I also ran the focused default-mode test locally on the checked-out head: 1 passed, 70 skipped. The linked issue #4049 (closed) already carries the port-collision half of the flake fixed separately (14_client_defined_tools.py now uses port 8004, distinct from 01's 8001), so this PR's narrower tmux scope is appropriate.

The hardcoded dir="/tmp" is Linux-only by design, which is acceptable here because the run-examples workflow runs on ubuntu-24.04 and tmux is Unix-only.

No material correctness, security, compatibility, or acceptance-criterion findings on the current head.

✅ APPROVED

@malhotra5
malhotra5 merged commit 106ddf9 into main Oct 5, 2026
72 of 74 checks passed
@malhotra5
malhotra5 deleted the fix-example-tmux-tmpdir branch October 5, 2026 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test-examples Run all applicable "examples/" files. Expensive operation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants