openclaw - 💡(How to fix) Fix exec: SSH commands SIGKILL'd when stdout exceeds ~1.2KB burst [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#57353Fetched 2026-04-08 01:50:43
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

SSH commands spawned via the exec tool are consistently SIGKILL'd when the remote command produces more than ~1,200 bytes of stdout in a single burst. This makes SSH file transfers, diffs, and any command with moderate output unusable.

Root Cause

SSH commands spawned via the exec tool are consistently SIGKILL'd when the remote command produces more than ~1,200 bytes of stdout in a single burst. This makes SSH file transfers, diffs, and any command with moderate output unusable.

Fix Action

Workaround

Rate-limit SSH output with micro-sleeps:

ssh host 'cat file | while IFS= read -r line; do echo "$line"; sleep 0.01; done'

Code Example

# Works (1,100 bytes)
ssh remote-host 'python3 -c "print(\"x\" * 1100)"'

# SIGKILL (1,300 bytes)
ssh remote-host 'python3 -c "print(\"x\" * 1300)"'

# Works — same data, rate-limited delivery
ssh remote-host 'for i in $(seq 1 200); do echo "line_$i: padding data"; sleep 0.01; done'

# Works — equivalent local command (no SSH), 50KB+
python3 -c "print('x' * 50000)"

# Works — curl 50KB from remote
curl -s 'https://httpbin.org/bytes/50000' | wc -c

---

ssh host 'cat file | while IFS= read -r line; do echo "$line"; sleep 0.01; done'
RAW_BUFFERClick to expand / collapse

GitHub Issue: exec SSH SIGKILL bug

Repo: https://github.com/openclaw/openclaw/issues/new Title: exec: SSH commands SIGKILL'd when stdout exceeds ~1.2KB burst

Body:

Summary

SSH commands spawned via the exec tool are consistently SIGKILL'd when the remote command produces more than ~1,200 bytes of stdout in a single burst. This makes SSH file transfers, diffs, and any command with moderate output unusable.

Reproduction

# Works (1,100 bytes)
ssh remote-host 'python3 -c "print(\"x\" * 1100)"'

# SIGKILL (1,300 bytes)
ssh remote-host 'python3 -c "print(\"x\" * 1300)"'

# Works — same data, rate-limited delivery
ssh remote-host 'for i in $(seq 1 200); do echo "line_$i: padding data"; sleep 0.01; done'

# Works — equivalent local command (no SSH), 50KB+
python3 -c "print('x' * 50000)"

# Works — curl 50KB from remote
curl -s 'https://httpbin.org/bytes/50000' | wc -c

Diagnosis

  • Not a size limit: 50KB local commands and 50KB curl downloads work fine
  • Not yieldMs: Tested with 20s and 30s yieldMs — same result
  • Not connection exhaustion: Reproduced after killing all existing SSH sessions
  • Not macOS/OS-level: Same SSH commands work fine from Terminal.app
  • Not PTY: Tested with pty: true — same result
  • Burst-rate specific: Adding sleep 0.01 between output lines (spreading the same bytes over time) works perfectly — even for 200+ lines (~4KB+)

The issue appears to be that SSH delivers decrypted output in TCP-sized bursts. When a burst exceeds ~1.2KB, it arrives at the pipe faster than the exec runner drains it. The session watchdog then sees a process that hasn't produced "drained" output and kills it.

subprocess.Popen().communicate() from within exec shows the SSH process hangs (not crashes) — confirming the pipe is filling up. OpenClaw's watchdog then SIGKILL's the hung process.

Environment

  • OpenClaw 2026.3.24
  • macOS 25.3.0 (arm64) — Apple Silicon Mac mini
  • SSH to DigitalOcean VPS (Amsterdam)
  • security.mac.pipe_enforce: 1 (macOS MAC pipe enforcement enabled)
  • OPENCLAW_BASH_PENDING_MAX_OUTPUT_CHARS: default (30,000)
  • PI_BASH_MAX_OUTPUT_CHARS: default (200,000)

Impact

Any SSH command producing >1.2KB of output is unusable from exec:

  • scp / rsync — hang and get killed
  • ssh host 'cat file' — killed for any file >1KB
  • ssh host 'diff ...' — killed if diff output >1KB
  • Effectively breaks remote server management from agents

Suggested Fix

The exec session watchdog should check whether there is data waiting in the pipe (readable bytes) before killing a process for inactivity. If the pipe has unread data, the process is producing output — it just hasn't been drained yet. Killing it is incorrect.

Alternatively, increase the pipe drain frequency for backgrounded sessions, or use non-blocking reads that keep up with burst arrivals.

Workaround

Rate-limit SSH output with micro-sleeps:

ssh host 'cat file | while IFS= read -r line; do echo "$line"; sleep 0.01; done'

extent analysis

Fix Plan

To address the issue of SSH commands being SIGKILL'd when stdout exceeds ~1.2KB burst, we will modify the subprocess.Popen().communicate() method to use non-blocking reads. This will prevent the pipe from filling up and triggering the session watchdog.

Here are the steps:

  • Modify the exec tool to use non-blocking reads when communicating with the SSH process.
  • Increase the pipe buffer size to reduce the likelihood of the pipe filling up.

Example code:

import subprocess
import select

# ...

# Create a Popen object with non-blocking reads
process = subprocess.Popen(['ssh', 'remote-host', 'command'],
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE)

# Use select to perform non-blocking reads
while process.poll() is None:
    readable, _, _ = select.select([process.stdout, process.stderr], [], [], 0.1)
    if readable:
        for stream in readable:
            data = stream.read(1024)
            if not data:
                break
            # Process the data
            print(data.decode())

# ...

Alternatively, you can use the threading module to create a separate thread for draining the pipe, ensuring that the pipe is drained regularly and preventing the session watchdog from killing the process.

Verification

To verify that the fix worked, you can test the SSH commands that previously exceeded the ~1.2KB burst limit. If the fix is successful, the commands should complete without being SIGKILL'd.

Example test:

ssh remote-host 'python3 -c "print(\"x\" * 1300)"'

If the command completes successfully, the fix has resolved the issue.

Extra Tips

  • Consider increasing the pipe buffer size to reduce the likelihood of the pipe filling up.
  • Use select or poll to perform non-blocking reads, ensuring that the pipe is drained regularly.
  • If using a separate thread for draining the pipe, ensure that the thread is properly synchronized to prevent data corruption or other issues.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix exec: SSH commands SIGKILL'd when stdout exceeds ~1.2KB burst [1 participants]