openclaw - 💡(How to fix) Fix Container accumulates zombie processes — needs tini or --init as PID 1 wrapper [1 comments, 2 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#77885Fetched 2026-05-06 06:19:47
View on GitHub
Comments
1
Participants
2
Timeline
1
Reactions
2
Timeline (top)
commented ×1

Root Cause

Node.js is not a proper init system. When it runs as PID 1, orphaned children get reparented to it, but it never calls waitpid(-1, WNOHANG) to reap them.

Fix Action

Fix

tini is already installed in the container at /usr/local/bin/tini. It just needs to be used as the entrypoint wrapper.

Dockerfile:

ENTRYPOINT ["tini", "--"]
CMD ["node", "/app/node_modules/.bin/openclaw", "start"]

Or docker run:

docker run --init ...

Or cloud deployments (Render, Railway, Fly):

tini -- node /app/node_modules/.bin/openclaw start

tini is 30KB, adds zero overhead, and is the standard solution. Docker's own --init flag literally injects tini.

Code Example

ENTRYPOINT ["tini", "--"]
CMD ["node", "/app/node_modules/.bin/openclaw", "start"]

---

docker run --init ...

---

tini -- node /app/node_modules/.bin/openclaw start
RAW_BUFFERClick to expand / collapse

Problem

When OpenClaw runs as PID 1 in a Docker container (the default), the Node.js process does not reap orphaned child processes. Node's default SIGCHLD handling only calls waitpid() for children it spawned via child_process — it does NOT perform the waitpid(-1) sweep that a proper init system does.

Every process spawned via the exec tool that exits becomes a zombie. Over a container's lifetime this accumulates hundreds of zombie entries in the process table.

Observed

  • PID 1: node /app/node_modules/.bin/openclaw start
  • After ~2 hours of normal operation: 148 zombie processes (bash, git, node, python, etc.)
  • Zombie count grows monotonically — they are never reaped
  • Chromium-based tools that exit as zombies poison lock files, preventing browser servers from restarting

Root Cause

Node.js is not a proper init system. When it runs as PID 1, orphaned children get reparented to it, but it never calls waitpid(-1, WNOHANG) to reap them.

Fix

tini is already installed in the container at /usr/local/bin/tini. It just needs to be used as the entrypoint wrapper.

Dockerfile:

ENTRYPOINT ["tini", "--"]
CMD ["node", "/app/node_modules/.bin/openclaw", "start"]

Or docker run:

docker run --init ...

Or cloud deployments (Render, Railway, Fly):

tini -- node /app/node_modules/.bin/openclaw start

tini is 30KB, adds zero overhead, and is the standard solution. Docker's own --init flag literally injects tini.

Impact

  • Process table pollution (148+ zombies after 2 hours)
  • Browser/Chromium lock files poisoned by zombie processes
  • PDF generation breaks when browse server is wedged
  • Eventually hits kernel PID limit on long-running containers

References

extent analysis

TL;DR

Use tini as an entrypoint wrapper to reap orphaned child processes when running Node.js as PID 1 in a Docker container.

Guidance

  • Use tini as the entrypoint wrapper by modifying the Dockerfile with ENTRYPOINT ["tini", "--"] and CMD ["node", "/app/node_modules/.bin/openclaw", "start"].
  • Alternatively, use the --init flag when running the Docker container, e.g., docker run --init ....
  • For cloud deployments, use tini as a prefix to the command, e.g., tini -- node /app/node_modules/.bin/openclaw start.
  • Verify the fix by checking the process table for zombie processes after running the container for an extended period.

Example

ENTRYPOINT ["tini", "--"]
CMD ["node", "/app/node_modules/.bin/openclaw", "start"]

Notes

This solution assumes that tini is already installed in the container at /usr/local/bin/tini. If not, it will need to be installed before using it as the entrypoint wrapper.

Recommendation

Apply the workaround by using tini as the entrypoint wrapper, as it is a standard solution with zero overhead and is already installed in the container.

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