# How Subsecond Hot-Patches Rust Code: Jump Table Indirection Explained

> Discover how Subsecond hot-patches Rust code via a lock-free jump table. Learn how function pointers are atomically swapped at runtime for efficient updates without memory modification.

- Repository: [Dioxus Labs/dioxus](https://github.com/DioxusLabs/dioxus)
- Tags: internals
- Published: 2026-07-23

---

**Subsecond hot-patches Rust code by routing every function call through a lock-free global jump table that atomically swaps pointers to freshly compiled functions at runtime, avoiding direct process memory modification.**

The Subsecond package in the DioxusLabs/dioxus repository enables true hot-reloading for Rust applications without restarting the process. Unlike traditional dynamic linking or runtime code injection, Subsecond implements hot-patching through an indirection layer that safely detours execution to updated code versions. This mechanism relies on a global jump table updated atomically whenever the Dioxus CLI detects source changes.

## The Global Jump Table Architecture

At the core of Subsecond’s hot-patching mechanism lies a lock-free `AtomicPtr<JumpTable>` called `APP_JUMP_TABLE`. This global pointer holds the current mapping from original function IDs to their latest memory addresses.

The jump table is lazily allocated during the first hot-reload operation and swapped atomically whenever a patch arrives. This design ensures that no active function calls encounter a partially updated table, as the atomic pointer swap guarantees thread-safe transitions between code versions. According to the source code in [`packages/subsecond/subsecond/src/lib.rs`](https://github.com/DioxusLabs/dioxus/blob/main/packages/subsecond/subsecond/src/lib.rs) (lines 73-80), the table declaration uses lock-free primitives to minimize runtime overhead during the detour checks.

## Detouring Calls with `subsecond::call`

User code enters the hot-patching system through the `subsecond::call` wrapper or the `HotFn` type. When a closure is executed via `subsecond::call`, the runtime builds a `HotFn` that performs a lookup in the global jump table before invoking the actual implementation.

As implemented in [`packages/subsecond/subsecond/src/lib.rs`](https://github.com/DioxusLabs/dioxus/blob/main/packages/subsecond/subsecond/src/lib.rs) (lines 41-71), the `subsecond::call` function checks whether a newer version of the function exists in the jump table. If a patched address is present, the call detours to that location; otherwise, the original implementation runs. This indirection happens transparently on every function call, ensuring that code updates take effect immediately after the jump table swap completes.

## The HotFn Wrapper and Retry Logic

`HotFn` serves as a thin wrapper around any `FnMut` closure, recording the original function in its `inner` field. On each invocation, `HotFn` queries the jump table for the current address via `ptr_address` and transmutes the resulting pointer into a callable function.

If a call would be stale—for instance, when a change occurs above the current call site in the stack—`HotFn` throws a `HotFnPanic`. This panic bubbles up to the next outer `subsecond::call`, which catches the error and retries the invocation against the updated jump table. The implementation in [`packages/subsecond/subsecond/src/lib.rs`](https://github.com/DioxusLabs/dioxus/blob/main/packages/subsecond/subsecond/src/lib.rs) (lines 50-88) demonstrates this retry mechanism, ensuring that in-flight calls gracefully transition to new code versions without corrupting the program state.

## Runtime Patch Application and ASLR Handling

When the Dioxus CLI detects a code change, it builds a patch library containing only the modified object files. The `apply_patch` function loads this library using platform-specific mechanisms—`dlopen` on native platforms or WebAssembly fetch on WASM—and extracts the exported symbols.

Because modern operating systems randomize memory layouts via Address Space Layout Randomization (ASLR), Subsecond first computes the offset between the original executable’s `main` symbol and the newly loaded library. This `aslr_reference` calculation allows the runtime to re-base all jump table entries correctly before installation. As shown in [`packages/subsecond/subsecond/src/lib.rs`](https://github.com/DioxusLabs/dioxus/blob/main/packages/subsecond/subsecond/src/lib.rs) (lines 107-149), the rebased pointers are written to a new jump table structure, and the global `APP_JUMP_TABLE` is atomically replaced. After the swap, any pending `HotFn` calls automatically resolve to the new code addresses.

## Build Pipeline: ThinLink and CLI Integration

The Dioxus CLI (`dx serve --hotpatch`) orchestrates the patching process through ThinLink, a lightweight linker that produces the patch library and generates jump-table metadata. The CLI streams this metadata to the running process via the Dioxus Devtools WebSocket protocol, triggering the runtime to call `apply_patch` and install the updates. This architecture separates the compilation and linking concerns from the runtime indirection mechanism, allowing Subsecond to maintain minimal overhead in the hot path while supporting complex rebuild scenarios.

## Practical Implementation Examples

The following examples demonstrate Subsecond’s API for hot-reloading Rust applications:

```rust
// Simple hot-reloaded loop
fn main() {
    // Every iteration goes through the jump table
    subsecond::call(|| {
        for i in 0..5 {
            // The inner call can be patched independently
            subsecond::call(|| {
                println!("iteration {i}");
            });
        }
    });
}

```

Each `subsecond::call` creates a `HotFn` that checks the jump table before invoking the closure. When the source file is edited and the CLI rebuilds the patch, the next iteration automatically runs the updated code.

```rust
// Manual use of HotFn and apply_patch
use subsecond::{HotFn, apply_patch, JumpTable};

fn add(a: i32, b: i32) -> i32 { a + b }

fn main() {
    let mut hot_add = HotFn::current(add);
    println!("2 + 3 = {}", hot_add.call((2, 3)));

    // Imagine we received a JumpTable from an external tool:
    let patch: JumpTable = /* ...deserialize... */;
    unsafe { apply_patch(patch).unwrap() };

    // After the patch, the same HotFn now calls the new implementation
    println!("2 + 3 = {}", hot_add.call((2, 3)));
}

```

**Key implementation details:**
- `HotFn::current` captures the original function and its identity in the jump table.
- `apply_patch` performs an atomic swap of the global jump table (marked `unsafe` because malformed tables can crash the process).
- Subsequent calls to `hot_add` resolve to the patched address without modifying the `hot_add` variable itself.

## Summary

- **Jump table indirection**: Subsecond routes all calls through `APP_JUMP_TABLE`, a lock-free atomic pointer to a function address mapping.
- **Transparent detours**: The `subsecond::call` wrapper and `HotFn` type check for updated implementations on every invocation with minimal overhead.
- **Safe atomic updates**: Patches are applied by computing ASLR offsets, rebasing pointers, and atomically swapping the global table, ensuring no thread observes a partial update.
- **Stale-call recovery**: The `HotFnPanic` mechanism allows outer wrappers to retry calls that would otherwise execute stale code.
- **Tooling integration**: ThinLink and the Dioxus CLI handle patch generation and delivery, while the runtime manages the address-space adjustments.

## Frequently Asked Questions

### How does Subsecond handle Address Space Layout Randomization (ASLR)?

Subsecond calculates an `aslr_reference` offset by comparing the address of the `main` symbol in the original executable against its location in the freshly loaded patch library. This offset is applied to all function pointers in the patch before they enter the jump table, ensuring that rebased addresses correctly point to the new code regardless of where the operating system loaded the library in memory.

### Is Subsecond’s hot-patching mechanism thread-safe?

Yes. The global jump table is protected by an `AtomicPtr`, allowing lock-free reads during the common case of function calls. When a patch arrives, Subsecond constructs the new table off-thread and performs a single atomic pointer swap. The `HotFn` retry logic handles the rare race condition where a call begins with the old table but completes after a swap, ensuring that no execution occurs at invalid addresses.

### What platforms does Subsecond support?

Subsecond supports native platforms using `dlopen` for dynamic library loading and WebAssembly targets using the fetch API. The ASLR rebasing logic is primarily relevant for native platforms where address space randomization is active; WASM environments use a different addressing model that does not require offset calculations.

### How does Subsecond differ from traditional DLL injection or dynamic linking?

Traditional dynamic linking resolves symbols at load time, while DLL injection typically overwrites process memory directly. Subsecond instead maintains a persistent indirection layer (the jump table) that can be updated atomically without modifying executable code segments. This approach avoids the safety hazards of self-modifying code and allows granular, function-level hot-patching rather than requiring entire library replacements.