2

std::mutex is nonrecursive, and violation of that is UB. So anything is possible in theory(including works as std::recursive_mutex)), but libc++ seems to work fine , this program outputs

bye

#include <iostream>
#include <mutex>

std::mutex m;
int main() {
    std::scoped_lock l1(m);
    std::scoped_lock l2(m);
    std::cout << "bye" << std::endl;
}

Is this intentional design decision in libc++ or just some accident(for example they could use same logic for mutex and recursive_mutex)?

libstdc++ hangs.

note: I am aware of that people should not rely on UB, so this is not about best practices, I am just curious about obscure implementation details.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • Please consider your choice of wording and the alternative "nested" for your "recursive". For example using two different mutexes seems better described as nested, while repeatedly locking the same might be "recursive". Also consider showing the (alternative) code which unlock them, the order of that might be relevant, or that it is not done. Does it change the observed behaviour. – Yunnosch Jan 12 '21 at 11:36
  • "Seems to work fine" is something UB can do. However, what you really mean is "Seems to work fine on my machine with a particular version of a compiler and set of options" – Marshall Clow Jan 12 '21 at 15:06
  • @MarshallClow I know, I was just curious about the causes of "working fine"... It was actually me not using -pthread in godbolt... dumb mistake but TIL something... – NoSenseEtAl Jan 12 '21 at 16:26

2 Answers2

4

It does not seem to be an intentional design decision. The libc++ implementation of std::mutex is just a wrapper around the platform's POSIX default mutex. Since that also is defined to have UB if locked recursively, they just inherited the fact that the platform's default POSIX mutex also happens to allow recursive locking.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
2

I get the opposite results: libc++ hangs and libstdc++ doesn't

The reason is that if the file is not compiled with -pthread, threading support is disabled and std::mutex::lock/unlock become noops. Adding -pthread makes both of them deadlock as expected.

libc++ is built with threading support by default and doesn't require the -pthread flag, so it std::mutex::lock does actually acquire a lock, creating the deadlock.

Artyer
  • 31,034
  • 3
  • 47
  • 75