jevsnes.git / apps / hotdemo / README.md

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.md is long is that every mistake here succeeds. Drop one compiler flag and subsecond::call quietly becomes a plain call; capture a variable in the closure and the patch "applies" and changes nothing; let the optimiser inline tick and there is nothing left to redirect. Each one prints "patch applied" and keeps printing v1.

Try it. Start it as above, then in a second shell inside nix develop, edit tick's string literal in src/main.rs and run tools/hotpatch/patch.sh //apps/hotdemo:hotdemo. Watch run/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

PathWhat
src/main.rstick (the one function to patch), main's loop, and the patch-file watcher.
BUCKThe 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/ →