Sitelet https://github.com/rust-lang/rust/issues/37612
Skip to content

Using pattern match directly on LockResult causes deadlock #37612

Description

@lloydmeta

Came across this as I was playing around with implementing memoisation via double-checked-locking with sync::RWLock:

The following, which puts the .read() result into a temporary binding works fine:

// ...
{
    let lock_result = self.cache.read(); // <-- temporary binding
    match lock_result {
        Ok(ref data) if data.len() > to => Some(data[to].clone()),
        _ => None,
    }
}
.unwrap_or_else(|| {
    // We need to write now, so get a write lock
    let mut data = self.cache.write().unwrap();
// ...

The following, which directly matches on the result of .read(), dies in a deadlock:

// ...
{
    match self.cache.read() { // <-- direct pattern matching
        Ok(ref data) if data.len() > to => Some(data[to].clone()),
        _ => None,
    }
}
.unwrap_or_else(|| {
    // We need to write now, so get a write lock
    let mut data = self.cache.write().unwrap();
// ...

I'm guessing the direct pattern match is compiled/desugared in a way that the RwLockReadGuard never goes out of scope and thus the read lock is never released, but I'm not sure if this is the expected behaviour. It certainly surprised me, especially since the entire "read" block is scoped by its own set of braces.

For extra context, here is the relevant part in my scratchpad project. I have a concurrency test for it that fails to finish if the pattern matching section is changed to match the latter case.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-destructorsArea: Destructors (`Drop`, …)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions