Skip to content

Instantly share code, notes, and snippets.

@maczniak
Last active May 12, 2023 07:46
Show Gist options
  • Save maczniak/4262b30ad3a64f7802d5dd9579ff3ee5 to your computer and use it in GitHub Desktop.
Save maczniak/4262b30ad3a64f7802d5dd9579ff3ee5 to your computer and use it in GitHub Desktop.
volatile global variable test in Rust (please use ArcSwap instead)
[package]
name = "memory-leak-test"
version = "0.0.1"
edition = "2021"
[dependencies]
actix-rt = "2.8"
actix-web = "4"
env_logger = "0.10"
log = "0.4"
lazy_static = "1.4"
use std::sync::atomic::{AtomicPtr, Ordering};
use std::ptr::null_mut;
use actix_rt::time;
use core::time::Duration;
use lazy_static::lazy_static;
#[derive(Debug, Clone)]
struct Dummy {
buffer: Vec<u32>,
}
impl Drop for Dummy {
fn drop(&mut self) {
log::info!("drop called");
}
}
lazy_static! {
static ref GLOBAL_PTR : AtomicPtr<Dummy> = AtomicPtr::new(null_mut::<Dummy>());
}
#[actix_web::main(flavor = "current_thread")]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let mut dummy = Box::new(Dummy { buffer: Vec::with_capacity(10_000_000) });
for _ in 0..10_000_000 {
dummy.buffer.push(1217);
}
log::info!("initial value {}", dummy.buffer[555]);
GLOBAL_PTR.store(Box::into_raw(dummy), Ordering::Relaxed);
log::info!("global_ptr address {:?}", std::ptr::addr_of!(GLOBAL_PTR));
unsafe {
log::info!("first fetch {}", (*GLOBAL_PTR.load(Ordering::Relaxed)).buffer[555]);
}
let mut handles = Vec::new();
for i in 0..10 {
let ii = i;
let handle = actix_rt::spawn(async move {
let mut interval = time::interval(Duration::from_secs(10));
loop {
interval.tick().await;
unsafe {
log::info!("fetch in thread #{} {:?}", ii, (*GLOBAL_PTR.load(Ordering::Acquire)).buffer[555]);
}
let mut dummy = Box::new(Dummy { buffer: Vec::with_capacity(10_000_000) });
for _ in 0..10_000_000 {
dummy.buffer.push(ii);
}
let new_ptr : &'static mut Dummy = Box::leak(dummy);
let old_ptr = GLOBAL_PTR.swap(new_ptr, Ordering::AcqRel);
unsafe {
drop(Box::from_raw(old_ptr));
}
}
});
handles.push(handle);
}
log::info!("out of loop");
for handle in handles {
let _ = handle.await;
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment