embassy
embassy copied to clipboard
To much yield_now() can panic!
It seems that yield_now()
can induce panic.
What happens is if we yield_now() in main() twice, we can generate panic.
This issue applies also on embedded systems / stm32.
To reproduce copy into embassy/examples/std/src/bin/tick.rs
and run
RUST_LOG=info cargo run --bin tick --release
#![feature(type_alias_impl_trait)]
use embassy_executor::executor::Spawner;
use embassy_util::channel::signal::Signal;
use embassy_util::yield_now;
use log::*;
static SIGNAL: Signal<u32> = Signal::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
env_logger::builder()
.filter_level(log::LevelFilter::Debug)
.format_timestamp_nanos()
.init();
spawner.spawn(task1()).unwrap();
spawner.spawn(task2()).unwrap();
yield_now().await;
// comment next line to not panic
yield_now().await;
SIGNAL.signal(1);
}
#[embassy_executor::task]
async fn task1() -> ! {
task_common(1).await
}
#[embassy_executor::task]
async fn task2() -> ! {
task_common(2).await
}
async fn task_common(id: i32) -> ! {
let mut i = 0;
let step = 1000000;
loop {
let x = SIGNAL.wait().await;
if x >= i {
info!("signal {} received {}", id, x);
i += step;
}
SIGNAL.signal(x + 1);
yield_now().await;
}
}
This is due to doing .wait()
on the same signal from 2 tasks at the same time.
There's a pending PR to switch Signal
to use the waitqueue
utils (#498). When that's done it won't panic, but the signal will only send the value to one task, not both, which is probably not what you want.
If you want "broadcast" capabilities, you can use pubsub. Alternatively, if you don't need async-waiting, a static
with a Mutex will be simpler to share state between tasks.
Thank You now it works.
Issue with server I was building, boiled down to this, and now when I am running with mutex instead of signal it works ok. Regarding documentation on signal, my understanding was that there is only one who receives signal, just like proposed PR. https://docs.embassy.dev/embassy/git/std/channel/signal/struct.Signal.html
Allows creating awaitable signals that may be passed between tasks. For a simple use-case where the receiver is only ever interested in the latest value of something, Signals work well.
Thank you for support and this work.
Fixed in #946