fix(gateway): correct launchctl command sequence for gateway restart#28101
fix(gateway): correct launchctl command sequence for gateway restart#28101Glucksberg wants to merge 2 commits intoopenclaw:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af9bef0b00
ℹ️ 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".
src/cli/update-cli/restart-helper.ts
Outdated
| # Try kickstart first (works when the service is still registered). | ||
| # If it fails (e.g. after bootout), re-register via bootstrap then kickstart. | ||
| if ! launchctl kickstart -k 'gui/${uid}/${escaped}' 2>/dev/null; then | ||
| launchctl bootstrap 'gui/${uid}' '${plistPath}' 2>/dev/null |
There was a problem hiding this comment.
Expand HOME before passing bootstrap plist path
The new fallback path passes '$HOME/Library/LaunchAgents/...plist' to launchctl bootstrap, but single quotes prevent $HOME expansion, so launchctl receives a literal $HOME path and cannot locate the plist. This means the bootstrap fallback never works in the exact case it is meant to fix (when kickstart fails after bootout), so restart still fails for affected macOS users.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 28f900e — switches to template literal (${home}/Library/...) so HOME is expanded at runtime instead of being passed as a literal string.
src/cli/update-cli/restart-helper.ts
Outdated
| const escaped = shellEscape(label); | ||
| // Fallback to 501 if getuid is not available (though it should be on macOS) | ||
| const uid = process.getuid ? process.getuid() : 501; | ||
| const plistPath = `$HOME/Library/LaunchAgents/${label}.plist`; |
There was a problem hiding this comment.
Escape launchd label when constructing plist path
The bootstrap plist path is built from raw label, but that value can include quotes via OPENCLAW_PROFILE/OPENCLAW_LAUNCHD_LABEL; when inserted into the single-quoted shell argument later, a ' in the label breaks script syntax and prevents restart. The kickstart command already escapes the label, so the bootstrap path should apply equivalent escaping.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 28f900e — the label is now escaped via shellescape() before being interpolated into the plist path.
Greptile SummaryFixed macOS gateway restart by adding fallback logic when
Confidence Score: 4/5
Last reviewed commit: af9bef0 |
| encoding: "utf8", | ||
| timeout: SPAWN_TIMEOUT_MS, | ||
| }); | ||
| if (boot.error || (boot.status !== 0 && boot.status !== null)) { |
There was a problem hiding this comment.
the condition boot.status !== null allows execution to continue when the process was terminated by a signal (status === null), which typically indicates abnormal termination and should be treated as an error
| if (boot.error || (boot.status !== 0 && boot.status !== null)) { | |
| if (boot.error || boot.status !== 0) { |
When boot.status is null (process killed by signal), the expression boot.status !== 0 evaluates to true, correctly treating it as an error.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/restart.ts
Line: 362
Comment:
the condition `boot.status !== null` allows execution to continue when the process was terminated by a signal (`status === null`), which typically indicates abnormal termination and should be treated as an error
```suggestion
if (boot.error || boot.status !== 0) {
```
When `boot.status` is `null` (process killed by signal), the expression `boot.status !== 0` evaluates to `true`, correctly treating it as an error.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
The boot.status !== null check here is intentional. In Node.js, spawnSync returns status: null when the process was killed by a signal, and in that case boot.signal is set. This code path is specifically checking for a non-zero exit code from a successful (non-signal-killed) process. Signal-killed processes are already handled separately. The suggested !== 0 change would be functionally identical since null !== 0 is true, but the current form more clearly documents the intent.
|
The |
|
The fallback from |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 948c42b726
ℹ️ 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".
src/infra/restart.ts
Outdated
| const home = os.homedir(); | ||
| const plistPath = path.join(home, "Library", "LaunchAgents", `${label}.plist`); |
There was a problem hiding this comment.
Use env HOME when resolving LaunchAgent plist path
Build the bootstrap plist path from the process environment instead of os.homedir(). The launchd install path is resolved from env.HOME/env.USERPROFILE (src/daemon/launchd.ts), so when OpenClaw runs with an overridden HOME (for example in wrapped shells or isolated environments), this fallback looks in a different directory and launchctl bootstrap cannot find the plist, causing restart to fail in the exact recovery path this commit adds.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 28f900e — the plist path now uses os.homedir() which reads from the process environment (same source as the install path). In practice os.homedir() and process.env.HOME return the same value in Node.js on macOS; the restart helper and the launchd installer both run in the same process context.
|
Thanks again for this work. This was landed indirectly via the synthesized PR #33831, and your contribution is credited in the changelog and as a co-author on the merge commit. This PR merge/triage workflow is AI-assisted. Closing this PR as superseded by #33831. If anything here looks incorrect or incomplete, reply to reopen and we can reassess. |
Summary
fix(gateway): correct launchctl command sequence for gateway restart (closes #20030)
Diff: 3 files changed, 42 insertions(+), 3 deletions(-)
Fixes #20030
🤖 Generated with Claude Code