Skip to content

Conversation

@ShoyuVanilla
Copy link

Fixes #376

#[test]
fn try_lock_no_block() {
    loom::model(|| {
        let lock = Rc::new(Mutex::new(0));
        let lock2 = lock.clone();

        let th = thread::spawn(move || {
            let _ = lock.try_lock(); // A
        });

        let guard = lock2.try_lock(); // B

        th.join().unwrap();

        drop(guard)
    })
}

With the above code, in some execution paths, the following happens:

  1. Thread 0 tries to acquire B then switched into thread 1 before finishing it
  2. Thread 1 tries to acquire A and blocks thread 0 in the following lines

    loom/src/rt/mutex.rs

    Lines 115 to 129 in dbf32b0

    // Block all **other** threads attempting to acquire the mutex
    for (id, thread) in execution.threads.iter_mut() {
    if id == thread_id {
    continue;
    }
    if let Some(operation) = thread.operation.as_ref() {
    if operation.object() == self.state.erase() {
    let location = operation.location();
    trace!(state = ?self.state, thread = ?id,
    "Mutex::post_acquire");
    thread.set_blocked(location);
    }
    }
    }
  3. Thread 0 is blocked, so it cannot join the thread handle

Similar thing happens with RwLock and the simple short circuit code I added prevents such paths

@mox692
Copy link
Member

mox692 commented Jun 17, 2025

Hi, I'm happy to review this, but it might take a bit of time since it's been a while since I last looked at the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loom reports deadlock for Mutex::try_lock

2 participants