jevsnes.git / apps / hotdemo / README.md
1# Chapter 15: hotdemo, a program that changes its mind
2
3Web developers are spoiled: save a file and the page updates without losing
4its state. Native programs usually make you stop, rebuild and start again,
5and for this project starting again means losing the game the bot was in
6the middle of. [Dioxus subsecond](https://github.com/DioxusLabs/dioxus) is a
7library that brings hot reloading to native Rust: it swaps the body of a
8function inside a running process. Its own tool, `dx`, does that by
9becoming your compiler and linker. This project builds with buck2 instead,
10so the patch had to be built a different way (chapter 27), and that needed
11proving somewhere small first.
12
13`hotdemo` is that somewhere. It is not part of the game. It does one thing,
14forever: once a second, print a line through `subsecond::call`, then look
15for a patch to apply.
16
17```bash
18nix develop -c buck2 run //apps/hotdemo:hotdemo > run/hotdemo.log
19```
20
21prints, at startup:
22
23```
24hotdemo pid=<pid> aslr_reference=0x<addr>
25```
26
27then one `hotdemo v1 tick=<n>` line a second. Edit the string in `tick`,
28run `tools/hotpatch/patch.sh //apps/hotdemo:hotdemo`, and a `hotdemo v2
29tick=<n>` line appears mid-run: same pid, no restart.
30
31> **Aside: the silent failures.** The reason this crate's `CLAUDE.md` is
32> long is that every mistake here *succeeds*. Drop one compiler flag and
33> `subsecond::call` quietly becomes a plain call; capture a variable in the
34> closure and the patch "applies" and changes nothing; let the optimiser
35> inline `tick` and there is nothing left to redirect. Each one prints
36> "patch applied" and keeps printing `v1`.
37
38> **Try it.** Start it as above, then in a second shell inside `nix
39> develop`, edit `tick`'s string literal in `src/main.rs` and run
40> `tools/hotpatch/patch.sh //apps/hotdemo:hotdemo`. Watch `run/hotdemo.log`.
41
42## For the people who maintain it
43
44The patch is delivered as `run/hotdemo.patch.json`, a serialised
45`subsecond_types::JumpTable`; hotdemo deletes it once applied (successfully
46or not), so a stale patch is never re-applied on the next second's check.
47`patch.sh` reads the pid and `aslr_reference` back out of
48`run/hotdemo.log`, which is why its output goes there.
49
50### In this folder
51
52| Path | What |
53| --- | --- |
54| [src/main.rs](src/main.rs) | `tick` (the one function to patch), `main`'s loop, and the patch-file watcher. |
55| [BUCK](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. |
56
57← Previous: [Chapter 14, replay-probe/](../replay-probe/) · Up: [apps](../) · Next: [Chapter 16, third-party/](../../third-party/) →