Chapter 15: hotdemo, a program that changes its mind
Web developers are spoiled: save a file and the page updates without losing
its state. Native programs usually make you stop, rebuild and start again,
and for this project starting again means losing the game the bot was in
the middle of. Dioxus subsecond is a
library that brings hot reloading to native Rust: it swaps the body of a
function inside a running process. Its own tool, dx, does that by
becoming your compiler and linker. This project builds with buck2 instead,
so the patch had to be built a different way (chapter 27), and that needed
proving somewhere small first.
hotdemo is that somewhere. It is not part of the game. It does one thing,
forever: once a second, print a line through subsecond::call, then look
for a patch to apply.
nix develop -c buck2 run //apps/hotdemo:hotdemo > run/hotdemo.log
prints, at startup:
hotdemo pid=<pid> aslr_reference=0x<addr>
then one hotdemo v1 tick=<n> line a second. Edit the string in tick,
run tools/hotpatch/patch.sh //apps/hotdemo:hotdemo, and a hotdemo v2 tick=<n> line appears mid-run: same pid, no restart.
Aside: the silent failures. The reason this crate's
CLAUDE.mdis long is that every mistake here succeeds. Drop one compiler flag andsubsecond::callquietly becomes a plain call; capture a variable in the closure and the patch "applies" and changes nothing; let the optimiser inlinetickand there is nothing left to redirect. Each one prints "patch applied" and keeps printingv1.
Try it. Start it as above, then in a second shell inside
nix develop, edittick's string literal insrc/main.rsand runtools/hotpatch/patch.sh //apps/hotdemo:hotdemo. Watchrun/hotdemo.log.
For the people who maintain it
The patch is delivered as run/hotdemo.patch.json, a serialised
subsecond_types::JumpTable; hotdemo deletes it once applied (successfully
or not), so a stale patch is never re-applied on the next second's check.
patch.sh reads the pid and aslr_reference back out of
run/hotdemo.log, which is why its output goes there.
In this folder
| Path | What |
|---|---|
| src/main.rs | tick (the one function to patch), main's loop, and the patch-file watcher. |
| BUCK | The rust_binary with the flags that make it patchable: -Csave-temps=true, -Clink-dead-code, -Cdebug-assertions=yes, and main exported as the ASLR reference point. |
← Previous: Chapter 14, replay-probe/ · Up: apps · Next: Chapter 16, third-party/ →