Kixiron / lasso

A fast, concurrent string interner
Apache License 2.0
137 stars 20 forks source link

Deadlock / panics for multi-threading in 0.7.0 #39

Closed abrenneke closed 1 year ago

abrenneke commented 1 year ago

Hi, just used lasso for the first time and I was getting deadlocks and panics inside of DashMap - had no idea what I was doing wrong. After like an hour of debugging I noticed that 0.7.0 just came out a week ago so on a hunch I tried 0.6.0 - deadlocks and panics went away!

If it helps here's the panic trace:

   0: std::panicking::begin_panic_handler
             at /rustc/3a8a131e9509c478ece1c58fe0ea2d49463d2300/library\std\src\panicking.rs:577
   1: core::panicking::panic_fmt
             at /rustc/3a8a131e9509c478ece1c58fe0ea2d49463d2300/library\core\src\panicking.rs:67
   2: core::panicking::panic
             at /rustc/3a8a131e9509c478ece1c58fe0ea2d49463d2300/library\core\src\panicking.rs:117
   3: dashmap::mapref::entry::VacantEntry<ref$<str$>,lasso::keys::Spur,ahash::random_state::RandomState>::insert<ref$<str$>,lasso::keys::Spur,ahash::random_state::RandomState>
             at C:\Users\Andy\.cargo\registry\src\index.crates.io-6f17d22bba15001f\dashmap-5.4.0\src\mapref\entry.rs:106
   4: enum2$<dashmap::mapref::entry::Entry<ref$<str$>,lasso::keys::Spur,ahash::random_state::RandomState> >::or_try_insert_with
             at C:\Users\Andy\.cargo\registry\src\index.crates.io-6f17d22bba15001f\dashmap-5.4.0\src\mapref\entry.rs:82
   5: lasso::threaded_rodeo::ThreadedRodeo<lasso::keys::Spur,ahash::random_state::RandomState>::try_get_or_intern
             at C:\Users\Andy\.cargo\registry\src\index.crates.io-6f17d22bba15001f\lasso-0.7.0\src\threaded_rodeo.rs:329
   6: lasso::threaded_rodeo::ThreadedRodeo<lasso::keys::Spur,ahash::random_state::RandomState>::get_or_intern<lasso::keys::Spur,ahash::random_state::RandomState,ref$<str$> >
             at C:\Users\Andy\.cargo\registry\src\index.crates.io-6f17d22bba15001f\lasso-0.7.0\src\threaded_rodeo.rs:289
Kixiron commented 1 year ago

Do you happen to have a minimal reproduction of any kind?

abrenneke commented 1 year ago

I think this is reproducing the deadlock! Sometimes it's printing 0, sometimes 0 and 1000, but never continues forever like it should. I'm on Windows if it makes a difference.

use lasso::ThreadedRodeo;
use std::sync::{Arc, Barrier};

fn main() {
    let thread_count = 10;
    let barrier = Arc::new(Barrier::new(thread_count));
    let interner = Arc::new(ThreadedRodeo::default());

    let mut handles = Vec::with_capacity(thread_count);
    for _ in 0..thread_count {
        let barrier = barrier.clone();
        let interner = interner.clone();
        handles.push(std::thread::spawn(move || {
            let mut i = 0;
            loop {
                interner.get_or_intern(format!("Hello, world! {}", i));

                if (i % 1000) == 0 {
                    barrier.wait();
                    println!("{}", i);
                }
                i += 1;
            }
        }));
    }

    for handle in handles {
        handle.join().unwrap();
    }
}
Kixiron commented 1 year ago

30a5413 fixes this locally (both for running the test and under ThreadSanitizer), can you confirm that you're no longer encountering the issue?

abrenneke commented 1 year ago

sorry for the late reply, but works great now! thanks!