fix(egg): the launcher drops Carbon's preloader for itself, not just the sidecar #17

Merged
whitlocktech merged 1 commits from fix/launcher-carbon-preload into main 2026-09-26 14:53:34 +00:00
Member

Found on phase 18 walk step 6: the first Carbon server built from the imported runicgateway-rust-autowipe egg. The Oxide server built from the same egg was correct.

The defect

On Carbon, the console showed the sidecar's whole --print-config JSON, token included and unframed, followed by:

[rust-link] Admin -> Rust -> Servers: server id 'main', sidecar URL http://192.168.0.12: (listening on )

The once-only token banner never appeared. The plugin still connected.

Carbon's entrypoint puts LD_PRELOAD=libdoorstop.so in front of the whole startup string. With Carbon's DOORSTOP_* environment set, that preloader breaks the launcher shell's own $(…): the child's output goes to the console and the capture comes back empty. env -u LD_PRELOAD on the sidecar wasn't enough, because the shell doing the capturing has the preload as well. I reproduced it in isolation:

carbon env:           X=$(env -u LD_PRELOAD echo hi)  →  "hi" on the console, captured=[]
carbon env, re-exec:  captured=[hi]

The fix

The launcher re-execs itself once without LD_PRELOAD, keeps the value aside, and gives it back to the game in run_game. The game is the only process that needs it.

Proof

  • Under Carbon's real environment.sh and libdoorstop.so, with a stub sidecar: the released v0.1.2 launcher reproduces the egg-carbon output exactly. This one prints the framed banner and server id 'egg-carbon', sidecar URL http://192.168.0.12:21019, and the game still receives LD_PRELOAD and DOORSTOP_ENABLED=1.
  • The four no-preload cases in ghcr.io/pterodactyl/games:rust (first boot, edited variable, Carbon config, installer config) are unchanged.

Merging releases v0.1.3. The launcher ships in the release, so the egg needs no re-import; a reinstall fetches it (§34.2.6).

  • AI-assisted: Claude Code (Claude Opus 5.5)

🤖 Generated with Claude Code

https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY

Found on phase 18 walk step 6: the first **Carbon** server built from the imported `runicgateway-rust-autowipe` egg. The Oxide server built from the same egg was correct. ## The defect On Carbon, the console showed the sidecar's whole `--print-config` JSON, **token included and unframed**, followed by: ``` [rust-link] Admin -> Rust -> Servers: server id 'main', sidecar URL http://192.168.0.12: (listening on ) ``` The once-only token banner never appeared. The plugin still connected. Carbon's entrypoint puts `LD_PRELOAD=libdoorstop.so` in front of the **whole** startup string. With Carbon's `DOORSTOP_*` environment set, that preloader breaks the launcher shell's own `$(…)`: the child's output goes to the console and the capture comes back empty. `env -u LD_PRELOAD` on the sidecar wasn't enough, because the shell doing the capturing has the preload as well. I reproduced it in isolation: ``` carbon env: X=$(env -u LD_PRELOAD echo hi) → "hi" on the console, captured=[] carbon env, re-exec: captured=[hi] ``` ## The fix The launcher re-execs itself once without `LD_PRELOAD`, keeps the value aside, and gives it back to the game in `run_game`. The game is the only process that needs it. ## Proof - Under Carbon's real `environment.sh` and `libdoorstop.so`, with a stub sidecar: the **released v0.1.2 launcher** reproduces the egg-carbon output exactly. **This one** prints the framed banner and `server id 'egg-carbon', sidecar URL http://192.168.0.12:21019`, and the game still receives `LD_PRELOAD` and `DOORSTOP_ENABLED=1`. - The four no-preload cases in `ghcr.io/pterodactyl/games:rust` (first boot, edited variable, Carbon config, installer config) are unchanged. Merging releases v0.1.3. The launcher ships in the release, so the egg needs no re-import; a reinstall fetches it (§34.2.6). - [x] AI-assisted: Claude Code (Claude Opus 5.5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
wtclaude added 1 commit 2026-09-26 09:28:24 +00:00
fix(egg): the launcher drops Carbon's preloader for itself, not just the sidecar
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 4m0s
af0e6be9f5
Carbon's entrypoint puts LD_PRELOAD=libdoorstop.so in front of the whole
startup string, and with Carbon's DOORSTOP_* environment that preloader
breaks the launcher shell's own command substitution: the sidecar's
--print-config output went straight to the console and the capture came
back empty. The first Carbon server built from the egg printed its config
JSON, token included, unframed, then "server id 'main', sidecar URL
http://192.168.0.12: (listening on )" and never the once-only banner.
`env -u LD_PRELOAD` on the sidecar alone was not enough: the shell doing
the capturing had the preload too.

The launcher now re-execs itself once without LD_PRELOAD, keeps it aside,
and gives it back to the game in run_game, the only process that needs it.

Reproduced and fixed under Carbon's real environment (environment.sh +
libdoorstop.so): the released launcher dumps the JSON; this one prints the
banner and "server id 'egg-carbon', sidecar URL http://192.168.0.12:21019",
and the game still gets LD_PRELOAD and DOORSTOP_ENABLED. The four
no-preload cases in the game image are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
whitlocktech merged commit e9b6778b78 into main 2026-09-26 14:53:34 +00:00
whitlocktech deleted branch fix/launcher-carbon-preload 2026-09-26 14:53:35 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RunicGateway/Rust-Link#17
No description provided.