Trying `subsecond` and: `Ignoring hotpatch since there is no ASLR reference`. What does it mean?
I'm trying for the first time https://docs.rs/subsecond/0.7.0-alpha.0/subsecond/index.html.
I have a small-size project (86642 lines of Rust code).
I changed this function:
impl Player {
pub fn to_css(&self, css_source: &str) -> Result<String> {
let result = css_source
.replace("{{number}}", &self.number.to_string())
.replace("{{height}}", &calculate_height(&self));
Ok(result)
}
}
to this:
impl Player {
pub fn to_css(&self, css_source: &str) -> Result<String> {
subsecond::call(|| {
let result = css_source
.replace("{{number}}", &self.number.to_string())
.replace("{{height}}", &calculate_height(&self));
Ok(result)
})
}
}
and launched this:
cargo binstall [email protected]
and then:
dx serve --package app --hotpatch
after a few moments it starts and axum is listening on its 8080 port. Good!
Then I change one line in the to_css function and boom:
[dev] Ignoring hotpatch since there is no ASLR reference. Is the client connected?
What does it mean?
Hey! We should probably change the logging here. This is because your client has not connected to the dioxus devtools server (we don't do this implicitly).
Add a
dioxus::dioxus_devtools::connect_subsecond();
to your main to connect to our devtools socket, and then things should start working.
Also, currently, capturing closures are not working properly with subsecond (they worked at some point) - will need to use the closure as a function:
impl Player {
pub fn to_css(&self, css_source: &str) -> Result<String> {
subsecond::current(|css_source| { /* ... */ }).call(css_source)
}
}
See this bevy demo as an example:
https://github.com/jkelleyrtp/subsecond-bevy-demo/blob/b33b702dd30067d262c7d6b9ec89f489b3bf26e6/src/main.rs#L7
Ok I tried. Unfortunately bad news.
-
dioxus::dioxus_devtools::connect_subsecond()doesn't,dioxus_devtools::connect_subsecond()works; -
subsecond::current:error[E0425]: cannot find function `current` in crate `subsecond` | 13 | subsecond::current(|css_source| { | ^^^^^^^ not found in `subsecond` | help: consider importing this function | 1 + use std::thread::current; | help: if you import `current`, refer to it directly | 13 - subsecond::current(|css_source| { 13 + current(|css_source| { | -
If I use
subsecond::call(|| {...})I get in the console:Hot-patching: C:\project\css.rs took 2735msso 2.7 seconds instead of 13 seconds with Cargo (night and day for me) BUT it seems like it's working and instead IT'S NOT WORKING! Poor me!
The function
to_cssgets called but it doesn't return the new (edited result). The string returned is always the one before the edit.
Subsecond::HotFn::current() - my bad!
Use the bevy template as a light guide.
Ok, thanks.
-
subsecond::HotFn::current(|css_source: &str| {}}).call((css_source))works but unfortunately the same as before: the functionto_cssgets called but it doesn't return the new (edited result). The string returned is always the one before the edit.
I also tried removing subsecond completely, using only dx serve --package app --hotpatch and the result is the same:
Hot-patching: C:\project\css.rs took 2881ms
but the result doesn't change after the edit and save.
What can be the cause?
It's a simple function that replaces parts of a string.
@frederikhors You might have to depend on the latest git version of subsecond. For me, the current alpha of subsecond did not work.
A day ago, I successfully used these versions.
dioxus-devtools = { version = "0.7.0-alpha.0", git = "https://github.com/DioxusLabs/dioxus.git", rev = "b2bd1f" }
and
cargo install dioxus-cli --git https://github.com/DioxusLabs/dioxus --rev b2bd1f
Ok, thanks.
Ok I added the git version at commit b2bd1f.
I start dx and after one edit to one file (no subsecond code involved) I get this:
[dev] Build failed: Runtime Error: Build panicked! JoinError::Panic(Id(270), "failed to resolve patch symbols: RuntimeError(Failed to find ___aslr_reference symbol\n\nStack backtrace:\n 0: git_index_checksum\n 1: git_index_checksum\n 2: git_filter_source_repo\n 3: git_filter_source_repo\n 4: git_filter_source_repo\n 5: git_filter_source_repo\n 6: git_filter_source_repo\n 7: git_index_checksum\n 8: git_index_checksum\n 9: git_index_checksum\n 10: git_index_checksum\n 11: git_index_checksum\n 12: git_index_checksum\n 13: git_index_checksum\n 14: git_index_checksum\n 15: git_index_checksum\n 16: git_index_checksum\n 17: git_index_checksum\n 18: BaseThreadInitThunk\n 19: RtlUserThreadStart)", ...)
What is it?
I fixed the issues with Runtime Error: Build panicked! JoinError::Panic(Id(270) by re-installing cargo install dioxus-cli --git https://github.com/DioxusLabs/dioxus --rev b2bd1f.
But now I'm trying it and it doesn't work. The string of the function called from axum API is the same, no matter what changes I made to the .rs file.
I'll create a reproduction ASAP.
Ok I created a reproduction:
Cargo.toml:
[package]
name = "app"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = "0.8.4"
dioxus-devtools = { version = "=0.7.0-alpha.0", git = "https://github.com/DioxusLabs/dioxus.git", rev = "b2bd1f" }
tokio = { version = "1.0", features = ["full"] }
[profile]
[profile.wasm-dev]
inherits = "dev"
opt-level = 1
[profile.server-dev]
inherits = "dev"
[profile.android-dev]
inherits = "dev"
main.rs:
use axum::{Router, routing::get};
#[tokio::main]
async fn main() {
dioxus_devtools::connect_subsecond();
let app = Router::new().route("/", get(handler));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
async fn handler() -> String {
let mut res = "Hello, World!".to_string();
res = res.replace("World", "Moon");
res
}
Steps:
-
start
dxwith:dx serve --hotpatch -
open the browser to http://localhost:3000
-
edit "Moon" with something else
-
reload the browser page
-
the text is the same, Moon is still there
@frederikhors Wait, I don't see the dioxus_devtools::subsecond::HotFn::current call in the reproduction?
@frederikhors Wait, I don't see the
dioxus_devtools::subsecond::HotFn::currentcall in the reproduction?
Doesn't work with or without it.
Ah, subsecond has a bug with async!
Apparently trying to do dioxus_devtools::subsecond::HotFn::current(handler) where handler is an async fn does not work for me (Windows 11).
Meanwhile rewriting it to be a fn -> impl Future does work.
use axum::{Router, routing::get};
#[tokio::main]
async fn main() {
dioxus_devtools::connect_subsecond();
let app = Router::new().route("/", get(handler_wrapper));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
async fn handler_wrapper() -> String {
dioxus_devtools::subsecond::HotFn::current(handler)
.call(())
.await
}
// Does NOT get hot patched
/*
async fn handler() -> String {
let mut res = "Booom, World!".to_string();
res = res.replace("World", "Moon");
res
}
*/
// Does get hot patched
fn handler() -> impl Future<Output = String> {
let mut res = "Booom, World!".to_string();
res = res.replace("World", "Moon");
async { res }
}
@jkelleyrtp Should I open a new issue to track that async bug?
I am getting a different error for axum, after I changed the code it shows the error
22:38:20 [dev] Build failed: Runtime Error: Build panicked! JoinError::Panic(Id(31), "failed to resolve patch symbols: RuntimeError(Failed to find ___aslr_reference symbol\n\nStack backtrace:\n 0: dx::build::patch::create_undefined_symbol_stub\n 1: dx::build::request::BuildRequest::build::{{closure}}\n 2: dx::build::builder::AppBuilder::patch_rebuild::{{closure}}\n 3: tokio::runtime::task::core::Core<T,S>::poll\n 4: tokio::runtime::task::harness::Harness<T,S>::poll\n 5: tokio::runtime::scheduler::multi_thread::worker::Context::run_task\n 6: tokio::runtime::context::scoped::Scoped<T>::set\n 7: tokio::runtime::context::runtime::enter_runtime\n 8: tokio::runtime::scheduler::multi_thread::worker::run\n 9: <tokio::runtime::blocking::task::BlockingTask<T> as core::future::future::Future>::poll\n 10: tokio::runtime::task::core::Core<T,S>::poll\n 11: tokio::runtime::task::harness::Harness<T,S>::poll\n 12: tokio::runtime::blocking::pool::Inner::run\n 13: std::sys::backtrace::__rust_begin_short_backtrace\n 14: core::ops::function::FnOnce::call_once{{vtable.shim}}\n 15: std::sys::pal::unix::thread::Thread::new::thread_start\n 16: <unknown>\n 17: <unknown>)", ...)
Cargo.toml
[package]
name = "axum-hello"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = "0.8.4"
tokio = { version = "1.45.1", features = ["full"] }
dioxus-devtools = { version = "0.7.0-alpha.0", git = "https://github.com/DioxusLabs/dioxus.git" }
src/main.rs
use axum::{response::Html, routing::get, Router};
#[tokio::main]
async fn main() {
dioxus_devtools::connect_subsecond();
let app = Router::new().route("/", get(handler));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
async fn handler() -> Html<&'static str> {
dioxus_devtools::subsecond::call(|| {
Html("<h1>Hello, World!</h1>")
})
}
One surprising thing I noticed after bevy compiles is that the file was modified, I have to reload my editor (helix) manually with :reload.
You might have a different version of Dioxus and the CLI. In the most recent commit we moved from __aslr_reference to just using 'main'
Ah nice, seemed to work now.
Can subsecond have serde being ^1 so that it can be more portable for packages that uses an older serde version? I wanted to add a hello world example to axum but it didn't work due to that error.
With the devtools at main branch the axum small example works. My real case still doesn't work. The string is not replaced. I cannot understand why. And I cannot create a reproduction because it's complex. Lot of async calls.
@frederikhors Have you been able to get it to work under some very specific circumstances in your real case? That might help the Dioxus team narrow it down.
One of the first things I tried in the reproduction case was "avoiding async". That seemed to work reliably. And then I tried out more cases.
async fn handler() -> String {
dioxus_devtools::subsecond::HotFn::current(sync_handler)
.call(())
.await
}
fn sync_handler() -> String {
let mut res = "Booom, World!".to_string();
res = res.replace("World", "Moon");
res
}
Another thing: If your real project has multiple crates, then it's very possible that it just outright won't work due to #4160
Yeah @stefnotch i have many crates. It may be.
dioxus_devtools::connect_subsecond(); was exactly what I needed.
I've been trying to get a working binary hotpatching example working on Windows, and up until now this was my latest stumbling block.
I do have other issues regarding the linker I'm now trying to sort out, first upon initial build and now with the invoked linker on code change, but this helped me advance a step.
The async issue was re-reported here https://github.com/DioxusLabs/dioxus/issues/4305
I think since the issue here was related to problems with setup, and subsecond now has a serve method as well as dioxus::serve, we can close this.