Skip to content

Gateway: stop and restart unmanaged listeners#39355

Merged
vincentkoc merged 8 commits intomainfrom
vincentkoc-code/gateway-stop-restart-no-service-manager
Mar 8, 2026
Merged

Gateway: stop and restart unmanaged listeners#39355
vincentkoc merged 8 commits intomainfrom
vincentkoc-code/gateway-stop-restart-no-service-manager

Conversation

@vincentkoc
Copy link
Copy Markdown
Member

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: openclaw gateway stop and openclaw gateway restart bail out with service disabled when the gateway is running under a container or another supervisor without a registered service manager unit.
  • Why it matters: container and foreground deployments cannot stop or gracefully restart the running gateway even though the process already handles SIGTERM and SIGUSR1 natively.
  • What changed: add a gateway-only not-loaded fallback that discovers listeners on the configured gateway port, sends SIGTERM for stop, sends SIGUSR1 for a single unambiguous listener on restart, and still runs the existing restart health checks and JSON responses.
  • What did NOT change (scope boundary): service-managed launchd/systemd/schtasks paths stay unchanged, Node daemon lifecycle stays unchanged, and ambiguous multi-listener restart cases still fail instead of guessing.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • openclaw gateway stop now stops unmanaged gateway listeners in container/supervisor deployments by sending SIGTERM when no service manager unit is loaded.
  • openclaw gateway restart now gracefully restarts a single unmanaged gateway listener by sending SIGUSR1 and keeping the existing health-check/JSON response path.
  • If multiple unmanaged listeners are found on the configured port, restart now fails with an explicit diagnostic instead of guessing which PID to signal.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS host running repo checks; issue targets Linux containers/headless supervisors
  • Runtime/container: Vitest unit tests + repo build/check gates
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): gateway port 18789

Steps

  1. Start the gateway under a supervisor or container without a service manager unit.
  2. Run openclaw gateway stop or openclaw gateway restart.
  3. Verify the CLI signals the unmanaged gateway process instead of returning service disabled.

Expected

  • Stop sends SIGTERM to the unmanaged gateway listener.
  • Restart sends SIGUSR1 to a single unmanaged listener and still waits for restart health checks.

Actual

  • Verified by lifecycle tests covering stop/restart fallback wiring, JSON responses, and preserved restart health checks.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: targeted Vitest coverage for unmanaged stop/restart fallback, full pnpm build, full pnpm check.
  • Edge cases checked: restart keeps the existing post-restart health checks; JSON responses still emit on fallback paths; restart fails on multiple unmanaged listeners instead of guessing.
  • What you did not verify: live container/manual signal behavior against a real Docker/Podman/LXC instance.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: revert the branch commits or fall back to the previous service-manager-only lifecycle behavior.
  • Files/config to restore: src/cli/daemon-cli/lifecycle-core.ts, src/cli/daemon-cli/lifecycle.ts
  • Known bad symptoms reviewers should watch for: unmanaged restart reporting success without the expected health-check wait, or restart signaling multiple candidate listeners.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: port-based PID discovery can find more than one gateway listener in unusual stale-process states.
    • Mitigation: stop dedupes and SIGTERMs all candidates; restart refuses to guess and errors with an explicit status --deep hint.
  • Risk: the generic lifecycle-core hook could accidentally change other daemon flows.
    • Mitigation: only gateway lifecycle wires the hook; Node and service-managed paths retain their old behavior and are covered by existing call sites.

@openclaw-barnacle openclaw-barnacle bot added cli CLI command changes commands Command implementations size: M labels Mar 8, 2026
@vincentkoc vincentkoc self-assigned this Mar 8, 2026
@openclaw-barnacle openclaw-barnacle bot added the maintainer Maintainer-authored PR label Mar 8, 2026
@vincentkoc vincentkoc marked this pull request as ready for review March 8, 2026 01:56
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 8, 2026

🔒 Aisle Security Analysis

We found 3 potential security issue(s) in this PR:

# Severity Title
1 🔵 Low Terminal/log injection via unsanitized port diagnostic errors in gateway restart health checks
2 🔵 Low Untrusted env/config can select port used to signal unmanaged gateway processes (local DoS)
3 🔵 Low Unverified PID signaling when service manager not loaded (port-based process.kill)

1. 🔵 Terminal/log injection via unsanitized port diagnostic errors in gateway restart health checks

Property Value
Severity Low
CWE CWE-117
Location src/cli/daemon-cli/restart-health.ts:270-272

Description

renderGatewayPortHealthDiagnostics() interpolates snapshot.portUsage.errors directly into user-visible output without sanitizing control characters/ANSI escapes.

  • snapshot.portUsage.errors originates from inspectPortUsage() (which captures raw stderr/stdout and exception strings from system tools like lsof, ss, netstat, wmic) and also from catch (err) { errors: [String(err)] }.
  • These error strings may contain newlines (\n/\r) and potentially terminal escape sequences (ANSI SGR, OSC-8 hyperlinks, etc.).
  • When printed to the terminal (or emitted in JSON warnings), this can enable log forging / terminal escape injection (CWE-117), e.g. a local attacker controlling a process name/command line that appears in diagnostics, or influencing tool output, could inject misleading lines or terminal control sequences.

Vulnerable code:

if (snapshot.portUsage.errors?.length) {
  lines.push(`Port diagnostics errors: ${snapshot.portUsage.errors.join("; ")}`);
}

Recommendation

Sanitize untrusted diagnostic text before rendering to terminal/log output.

Use existing sanitizers (e.g. sanitizeTerminalText or sanitizeForLog) on each error string (and ideally also on listener commandLine/command fields when formatting port diagnostics).

Example fix:

import { sanitizeTerminalText } from "../../terminal/safe-text.js";

if (snapshot.portUsage.errors?.length) {
  const safeErrors = snapshot.portUsage.errors.map((e) => sanitizeTerminalText(String(e)));
  lines.push(`Port diagnostics errors: ${safeErrors.join("; ")}`);
}

If multi-line error details are valuable, consider splitting into multiple sanitized lines rather than embedding raw newlines into a single log line.


2. 🔵 Untrusted env/config can select port used to signal unmanaged gateway processes (local DoS)

Property Value
Severity Low
CWE CWE-15
Location src/cli/daemon-cli/lifecycle.ts:28-38

Description

The new unmanaged stop/restart fallback can send signals to processes based on a port value derived from environment/config, which can be influenced by untrusted context.

In resolveGatewayLifecyclePort():

  • The port is resolved from the service's ExecStart args (--port ...) or from resolveGatewayPort(config, mergedEnv).
  • mergedEnv is built from process.env plus any service-defined environment.
  • resolveGatewayPort() honors OPENCLAW_GATEWAY_PORT (and config gateway.port).

When the service manager is not loaded, runDaemonStop() / runDaemonRestart() will use that resolved port to find listener PIDs and then send signals (SIGTERM/SIGUSR1).

Because the CLI loads dotenv from the current working directory (see infra/dotenv.ts, dotenv.config() default), an attacker who can control the directory where a victim runs openclaw gateway stop/restart can drop a .env file setting e.g. OPENCLAW_GATEWAY_PORT and/or OPENCLAW_CONFIG_PATH (pointing to an attacker-controlled config) to steer which port is targeted. This enables a local denial-of-service against openclaw processes listening on an attacker-chosen port whenever the service is not loaded.

Vulnerable logic (port resolution feeding process signaling) is introduced by the new unmanaged stop/restart behavior.

Recommendation

Treat the unmanaged stop/restart path as a safety-critical operation and avoid resolving the target port from ambient/untrusted configuration.

Recommended changes:

  1. Require an explicit port for unmanaged signaling, or default to the compiled-in default port only.
  2. Do not honor OPENCLAW_GATEWAY_PORT / config overrides for unmanaged kill/restart unless the user explicitly opts in.
  3. (Optional) Add a confirmation/warning when targeting a non-default port.

Example hardening approach:

import { DEFAULT_GATEWAY_PORT } from "../../config/paths.js";
import { parsePort } from "./shared.js"; // or wherever parsePort is exported

function resolveUnmanagedSignalPort(opts: { port?: string }): number {// Only trust an explicit CLI option (not dotenv/config/service env) for signaling.
  return parsePort(opts.port) ?? DEFAULT_GATEWAY_PORT;
}

Then use this value for stopGatewayWithoutServiceManager() / restartGatewayWithoutServiceManager() instead of resolveGatewayLifecyclePort().

If you need to preserve configurability, consider only trusting service-managed configuration (the installed unit’s --port) and ignoring cwd-loaded dotenv/config for these lifecycle actions.


3. 🔵 Unverified PID signaling when service manager not loaded (port-based process.kill)

Property Value
Severity Low
CWE CWE-362
Location src/cli/daemon-cli/lifecycle.ts:40-71

Description

The new unmanaged gateway stop/restart paths signal processes based on PIDs discovered by looking up listeners on a TCP port, without strong verification that the target process is actually the intended OpenClaw gateway instance.

In src/cli/daemon-cli/lifecycle.ts:

  • PIDs are derived from findGatewayPidsOnPortSync(port) and only filtered for pid > 0.
  • stopGatewayWithoutServiceManager() then sends SIGTERM to every PID found.
  • restartGatewayWithoutServiceManager() sends SIGUSR1 to the single PID found.

Security impact:

  • Process identity is not verified (no check of executable path, full cmdline, uid, or a gateway-specific marker). Anything that ends up in findGatewayPidsOnPortSync() results can be signaled.
  • TOCTOU / PID reuse risk: between port inspection and process.kill, the original process can exit and the PID can be reused, causing signals to be delivered to an unintended process.
  • If the CLI is run with elevated privileges (e.g., via sudo), this becomes a stronger local denial-of-service primitive because it can signal other users’ processes.

Vulnerable code:

for (const pid of pids) {
  process.kill(pid, "SIGTERM");
}
...
process.kill(pids[0], "SIGUSR1");

Recommendation

Harden unmanaged stop/restart by validating process identity immediately before signaling.

Suggested defenses (can be combined):

  1. Verify the listener is actually the gateway using stronger attributes:

    • command line contains an expected marker (e.g., openclaw-gateway), and/or
    • executable path matches the expected installation path, and/or
    • the listener uid matches the current uid (unless explicitly allowed).
  2. Re-check that the PID is still the listener on that port right before signaling (mitigates PID reuse).

  3. Handle ESRCH/EPERM safely: treat ESRCH as already-stopped; report EPERM with a clear message.

Example approach (pseudo-code):

import { inspectPortUsage } from "../../infra/ports-inspect.js";

async function safeSignalGatewayByPort(port: number, signal: NodeJS.Signals) {
  const usage = await inspectPortUsage(port);
  const candidates = usage.listeners
    .filter(l => typeof l.pid === "number")
    .filter(l => (l.commandLine ?? l.command ?? "").toLowerCase().includes("openclaw-gateway"));// optionally also enforce same-user:// .filter(l => l.user === os.userInfo().username)

  if (candidates.length !== 1) throw new Error("expected exactly one gateway listener");

  const pid = candidates[0].pid!;// Re-verify PID still listening (repeat inspectPortUsage or /proc check) before kill
  process.kill(pid, signal);
}

Also consider requiring an explicit --force flag before killing unmanaged processes, and/or printing details (pid + cmdline + user) for interactive confirmation when not using --json.


Analyzed PR: #39355 at commit 54e0861

Last updated on: 2026-03-08T02:27:32Z

Latest run failed. Keeping previous successful results. Trace ID: 019ccb38d4c2db0bc2a616402606c682.

Last updated on: 2026-03-08T02:28:15Z

@openclaw-barnacle openclaw-barnacle bot removed the commands Command implementations label Mar 8, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR adds an unmanaged-listener fallback to openclaw gateway stop and openclaw gateway restart so that container/supervisor deployments no longer receive a service disabled no-op when no service-manager unit is registered.

The implementation is clean and well-scoped:

  • The onNotLoaded hook is opt-in and wrapped in try/catch at call sites, ensuring exceptions from process.kill() surface as structured error messages
  • PID deduplication via Set before signalling is a good defensive measure
  • The managed paths (launchd/systemd/schtasks) remain completely untouched
  • Restart properly fails with a diagnostic when multiple listeners are found, avoiding guessing
  • Test coverage covers the key new behaviors: signal delivery, JSON response handling, and post-restart health checks

Confidence Score: 4/5

  • Safe to merge. Changes are narrowly scoped to the unmanaged-listener fallback path, with no modifications to managed-service (launchd/systemd/schtasks) code paths.
  • The PR is well-designed with clean separation of concerns: unmanaged paths are opt-in via the onNotLoaded callback, proper error handling via try/catch, and full preservation of existing health checks and validation. The implementation defensively handles edge cases (PID dedup, explicit failure on multi-listener restarts). Test coverage is solid for the new behaviors. The core concern around logical consistency in post-restart health checks is mitigated by platform-specific guards (includeUnknownListenersAsStale is Windows-only) and the acknowledged low practical risk. Score is 4/5 rather than 5/5 purely due to the one untested code path (stale-PID recovery in unmanaged restart on Windows), though this path is unlikely to execute in practice given Windows limitations with SIGUSR1.
  • No files require special attention. All changes follow established patterns and preserve backward compatibility.

Last reviewed commit: 042d212

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 042d21214f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@vincentkoc
Copy link
Copy Markdown
Member Author

Addressed the unmanaged restart post-check issue.

What changed:

  • unmanaged onNotLoaded restart no longer flows into the service-managed waitForGatewayHealthyRestart() path
  • added a separate listener/probe-only wait path in src/cli/daemon-cli/restart-health.ts
  • kept stale-PID cleanup and service.restart() retry logic scoped to service-managed restarts only
  • added regression coverage proving unmanaged restart uses the new path and does not call the service-managed health/retry flow

Verification:

  • pnpm vitest src/cli/daemon-cli/lifecycle.test.ts src/cli/daemon-cli/lifecycle-core.test.ts
  • pnpm check

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54e0861de5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@vincentkoc
Copy link
Copy Markdown
Member Author

Validated both follow-up findings on the current branch state.

  1. Undefined loadConfig() fallback: valid
  • the unmanaged stop/restart catch path had regressed to an out-of-scope loadConfig() reference after the rebase
  • fixed by routing those fallbacks back through readBestEffortConfig() and an env-only final fallback
  1. Port-derived PID signaling too loose: valid enough to harden
  • the fallback was still trusting findGatewayPidsOnPortSync(port) too much before signaling
  • tightened it by re-reading live process argv before every unmanaged SIGTERM/SIGUSR1 and only signaling processes that still look like an OpenClaw gateway process
  • added regression coverage that non-gateway argv on the same candidate PID is skipped instead of being signaled

Verification:

  • pnpm vitest src/cli/daemon-cli/lifecycle.test.ts src/cli/daemon-cli/lifecycle-core.test.ts
  • pnpm build
  • pnpm check

@vincentkoc
Copy link
Copy Markdown
Member Author

Follow-up on the latest review batch:

  • The two low findings against commit 042d212 are stale on current PR head; both were already fixed earlier on this branch.
  • I also addressed the unmanaged restart false-positive case: when the running gateway reports commands.restart=false, the CLI now fails before sending unmanaged SIGUSR1 instead of treating a still-healthy port as proof of restart.

Verification:

  • pnpm vitest src/cli/daemon-cli/lifecycle.test.ts src/cli/daemon-cli/lifecycle-core.test.ts
  • pnpm build
  • pnpm check

@vincentkoc vincentkoc merged commit bf9c362 into main Mar 8, 2026
31 of 34 checks passed
@vincentkoc vincentkoc deleted the vincentkoc-code/gateway-stop-restart-no-service-manager branch March 8, 2026 02:20
@vincentkoc
Copy link
Copy Markdown
Member Author

Landed in main: bf9c362

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0ee2386ac2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +57 to +59
if (!normalized.includes("gateway")) {
return false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept openclaw-gateway argv in unmanaged PID filter

The unmanaged fallback now depends on isGatewayArgv, but this guard exits early unless one argv token is exactly gateway. A process launched directly as openclaw-gateway (for example ['/usr/local/bin/openclaw-gateway', ...]) has no standalone gateway token, so its PID is filtered out and openclaw gateway stop/restart reports the service as not loaded instead of signaling the live unmanaged listener.

Useful? React with 👍 / 👎.

Comment on lines +115 to +117
if (!args || !isGatewayArgv(args)) {
throw new Error(`refusing to signal non-gateway process pid ${pid}`);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Tolerate vanished PID during unmanaged signal dispatch

After discovering listener PIDs, signalGatewayPid re-reads process args and throws when the cmdline cannot be read, which turns a normal race (PID exits between scan and signal) into a hard gateway stop/restart failed path. In busy container/supervisor environments this can make stop/restart fail even when the target process has already exited or is exiting, so the fallback should treat missing cmdline/ESRCH as best-effort instead of fatal.

Useful? React with 👍 / 👎.

openperf pushed a commit to openperf/moltbot that referenced this pull request Mar 8, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
mcaxtr pushed a commit to mcaxtr/openclaw that referenced this pull request Mar 8, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
Saitop pushed a commit to NomiciAI/openclaw that referenced this pull request Mar 8, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
GordonSH-oss pushed a commit to GordonSH-oss/openclaw that referenced this pull request Mar 9, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
jenawant pushed a commit to jenawant/openclaw that referenced this pull request Mar 10, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
dhoman pushed a commit to dhoman/chrono-claw that referenced this pull request Mar 11, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
senw-developers pushed a commit to senw-developers/va-openclaw that referenced this pull request Mar 17, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
V-Gutierrez pushed a commit to V-Gutierrez/openclaw-vendor that referenced this pull request Mar 17, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled

(cherry picked from commit bf9c362)
alexey-pelykh pushed a commit to remoteclaw/remoteclaw that referenced this pull request Mar 22, 2026
* Daemon: allow unmanaged gateway lifecycle fallback

* Status: fix service summary formatting

* Changelog: note unmanaged gateway lifecycle fallback

* Tests: cover unmanaged gateway lifecycle fallback

* Daemon: split unmanaged restart health checks

* Daemon: harden unmanaged gateway signaling

* Daemon: reject unmanaged restarts when disabled

(cherry picked from commit bf9c362)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli CLI command changes maintainer Maintainer-authored PR size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: openclaw gateway restart/stop fail in containers without systemd

1 participant