Skip to content

fix(launchd/macos): prevent restart loop by using KeepAlive.SuccessfulExit + ThrottleInterval#22224

Open
ashiabbott wants to merge 4 commits intoopenclaw:mainfrom
ashiabbott:fix/launchagent-keepalive-successfulexit
Open

fix(launchd/macos): prevent restart loop by using KeepAlive.SuccessfulExit + ThrottleInterval#22224
ashiabbott wants to merge 4 commits intoopenclaw:mainfrom
ashiabbott:fix/launchagent-keepalive-successfulexit

Conversation

@ashiabbott
Copy link

@ashiabbott ashiabbott commented Feb 20, 2026

Summary\n\nFixes LaunchAgent restart-loop behavior when both launchd and the app touch gateway lifecycle.\n\n### What changed\n- Daemon LaunchAgent plist now uses:\n - KeepAlive = { SuccessfulExit = true }\n - ThrottleInterval = 5\n- Service audit now validates:\n - KeepAlive dict form with SuccessfulExit: true\n - ThrottleInterval = 5\n- macOS app LaunchAgent plist updated to match the same KeepAlive/Throttle semantics (prevents app/launchd lifecycle conflicts).\n\n### Why\nA bare KeepAlive=true can fight app-managed lifecycle operations and trigger repeated relaunch behavior. Using SuccessfulExit + throttle aligns restart policy and avoids rapid loops.\n\n## Validation\n- daemon tests (launchd plist + audit + install) included in branch\n- macOS LaunchAgent plist write-path updated in app code\n\n## Issues\n- Closes #20257 (Workshop #474)

Greptile Summary

This PR fixes a LaunchAgent restart-loop issue on macOS by changing KeepAlive from a simple boolean to a dictionary with SuccessfulExit: true, and adds a 5-second ThrottleInterval. The changes apply to both the daemon LaunchAgent plist and the macOS app's LaunchAgent plist, preventing conflicts when both launchd and the app manage gateway lifecycle.

Key changes:

  • Updated buildLaunchAgentPlist to emit KeepAlive as <dict><key>SuccessfulExit</key><true/></dict> instead of bare <true/>
  • Added ThrottleInterval set to 5 seconds in both daemon and app LaunchAgent plists
  • Enhanced service audit to validate the new KeepAlive structure and ThrottleInterval
  • Added comprehensive tests for plist generation, installation, and audit validation
  • Also includes Matrix extension changes for LaTeX rendering with data-mx-maths attributes (commits 8f2a001, 5819263)

Matrix changes context:
The Matrix changes add support for rendering LaTeX math expressions using the data-mx-maths format for KaTeX support in Element clients. The implementation extracts LaTeX before markdown processing, preserves it during rendering, then converts to the appropriate HTML format.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The changes are well-tested with comprehensive test coverage for both the launchd plist generation and service audit validation. The fix addresses a specific, documented issue ([Bug]: LaunchAgent KeepAlive: true causes restart loop when App and launchd both manage gateway lifecycle #20257) with a targeted solution. All tests validate the new KeepAlive dictionary structure and ThrottleInterval. The Matrix changes include thorough test coverage for LaTeX rendering edge cases. No breaking changes or risky refactoring detected.
  • No files require special attention

Last reviewed commit: 85d8c6a

(4/5) You can add custom instructions or style guidelines for the agent here!

GitHub Actions added 4 commits February 20, 2026 16:06
…Element

Detects LaTeX math expressions in messages and converts them to Matrix
data-mx-maths format so Element Desktop/Web with Labs enabled can render
via KaTeX. Handles:
- Display math: \\$\$...\$\$\ and \\[...\]\
- Inline math: \\$...\$\ and \\(...\)\
- Protects LaTeX in code blocks from conversion

Fixes openclaw#467: Element Desktop doesn't render LaTeX from OpenClaw messages
- Before: formatted_body was plain HTML with literal dollar signs
- After: formatted_body uses data-mx-maths markup for KaTeX rendering

Tests: 12/12 pass (matrix format tests including LaTeX conversion cases)
... delimiters that form a standalone paragraph are emitted as
<div data-mx-maths='...'>, which Element Desktop renders via KaTeX.
Display delimiters embedded mid-sentence fall back to a <span> so the
surrounding paragraph HTML stays valid.  Inline \$...\$, \[...\], and
\(...\) are unchanged.

Code spans and fenced code blocks are protected before LaTeX extraction
so e.g. \$\^2\$\$ stays literal text and never gets converted.

All replacement calls now use split/join instead of String.replace() to
avoid the '' escape hazard with LaTeX content.

Closes openclaw#20276 (migrated as Workshop task openclaw#467)
…eway

Replace bare KeepAlive=true with { SuccessfulExit: true } in the
LaunchAgent plist. This makes launchd only restart the gateway on a
crash exit, not when it is intentionally stopped by the App's
GatewayLaunchAgentManager or by a kickstart -k call.

Also add ThrottleInterval=5 to prevent exponential backoff from
compressing rapid crash/restart cycles.

Audit changes:
- launchd-keep-alive now flags any plist that does NOT have the
  KeepAlive { SuccessfulExit: true } dict form (including old true plists)
- New launchd-throttle-interval audit code flags plists missing
  ThrottleInterval=5

Tests (28 pass):
- buildLaunchAgentPlist produces SuccessfulExit dict + ThrottleInterval=5
- installLaunchAgent writes plist with new KeepAlive form
- auditGatewayServiceConfig (darwin) flags legacy KeepAlive=true + missing
  ThrottleInterval as issues
- auditGatewayServiceConfig (darwin) accepts new-format plists cleanly

Closes openclaw#20257 (migrated as Workshop task openclaw#474)
@openclaw-barnacle openclaw-barnacle bot added channel: matrix Channel integration: matrix app: macos App: macos gateway Gateway runtime size: M labels Feb 20, 2026
@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Feb 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos channel: matrix Channel integration: matrix gateway Gateway runtime size: M stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: LaunchAgent KeepAlive: true causes restart loop when App and launchd both manage gateway lifecycle

1 participant