rtic-rs / rtic

Real-Time Interrupt-driven Concurrency (RTIC) framework for ARM Cortex-M microcontrollers

Home Page:https://rtic.rs

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

rtic-sync: make_channel is unsafe

wiktorwieclaw opened this issue · comments

/// Creates a split channel with `'static` lifetime.
#[macro_export]
macro_rules! make_channel {
    ($type:path, $size:expr) => {{
        static mut CHANNEL: $crate::channel::Channel<$type, $size> =
            $crate::channel::Channel::new();

        // SAFETY: This is safe as we hide the static mut from others to access it.
        // Only this point is where the mutable access happens.
        unsafe { CHANNEL.split() }
    }};
}

You can get multiple receivers to one (mpsc) channel using something like this:

use rtic_sync::channel::{Sender, Receiver};

fn main() {
    let (s1, r1) = test();
    let (s2, r2) = test();
}

fn test() -> (Sender<'static, i32, 1>, Receiver<'static, i32, 1>) {
    rtic_sync::make_channel!(i32, 1)
}

I suggest using static_cell or doing a manual runtime check inside the Channel impl, like thingbuf's StaticChannel

Alternatively, removing the unsafe block around the CHANNEL.split() could force the user/caller of the macro to acknowledge the unsafety, with docs on the macro about the how/why