Always “unfair double lock” when mutex is in struct instance (BUG?)

I have a StringMap, which maps to struct instances, which reside on the heap. In each instance I have a mutex.

It is not possible to lock such a mutex, though. Locking exactly once triggers “unfair double lock”. Even when I step through the code with the debugger there is no second lock (there also is no second one in the source code).

Is this a bug in Zig or the standard-library, or am I missing something?

Share your code. Are you properly initializing the mutex?

How do I do that? The mutex ist just initialized with .{}

Code sample:

    fn waitForValue(self: *ConfirmationMessage) [:0] const u8 {
        self.mutex.lock();
        defer self.mutex.unlock();

        self.wait_for_confirmation = true;

        while (self.wait_for_confirmation) {
            self.cv.wait(&self.mutex);
        }

        if (self.value) |value_| {
            return value_;
        }
        else {
            unreachable;
        }
    }

is there any recursion going on, specifically with self.cv.wait or does it try to lock the mutex, even indirectly?

The problem was solved by having pointer to struct instead of struct as the data type of the hashmap. The double locks came from the hashmap implementation copying around data including the mutex.

1 Like

This is incorrect. Reading of wait_for_confirmation needs to be atomic. As is, the compiler is free to optimize this as an infinite loop.

1 Like

self.wait_for_confirmation is a boolean flag, which is set from another thread. It corresponds to predicate in this example:

https://ziglang.org/documentation/0.15.2/std/#std.Thread.Condition

Note that in the example, a lock is taken in the producer and the consumer. This provides synchronization between threads. You either need a lock or to use an atomic variable. A simple global variable doesn’t work reliably for this because there is no synchronization between threads.

2 Likes