[Issue 22555] New: Recursively locked mutexes are not fully released by Condition.wait

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Nov 30 11:54:38 UTC 2021


https://issues.dlang.org/show_bug.cgi?id=22555

          Issue ID: 22555
           Summary: Recursively locked mutexes are not fully released by
                    Condition.wait
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: druntime
          Assignee: nobody at puremagic.com
          Reporter: default_357-line at yahoo.de

Consider this code:

import std;

import core.sync.condition;
import core.sync.mutex;
import core.sync.semaphore;
import core.thread;

class A
{
    int value;
    Condition condition;
    this()
    {
        condition = new Condition(new Mutex(this));
    }
    void set(int i)
    {
        synchronized (this)
        {
            value = i;
            this.condition.notifyAll;
        }
    }
    void wait(int i)
    {
        synchronized (this)
        {
            while (this.value != i)
            {
                condition.wait;
            }
        }
    }
}

void main() {
    auto done = new Semaphore;
    auto a = new A;
    task({
      synchronized (a)
      {
        writefln!"Wait for a to be 5";
        a.wait(5);
        writefln!"Wait done.";
      }
      done.notify;
    }).executeInNewThread;
    writefln!"Let task start up.";
    Thread.sleep(100.msecs);
    writefln!"Set a to 5.";
    a.set(5);
    writefln!"Wait for task to be done.";
    done.wait;
    writefln!"Done.";
}

Naively we would expect this sequence of operations:

Thread starts.
Thread waits on a.value == 5
main sets a.value to 5
Thread finishes waiting and signals done.
Main awaits done and returns.

This does not happen on Posix, because pthreads recursive mutexes have a
dangerous interaction with condition variables. 

See https://linux.die.net/man/3/pthread_cond_wait "These functions atomically
release _mutex_" in conjunction with
https://linux.die.net/man/3/pthread_mutex_lock "Each time the thread unlocks
the mutex, the lock count shall be decremented by one. When the lock count
reaches zero, the mutex shall become available for other threads to acquire."

As demonstrated, the effect of this is that after pthread_cond_wait, the mutex
is *not* available for other threads to acquire!

This causes the example to block forever.

--


More information about the Digitalmars-d-bugs mailing list