The following code hangs because of multiple calls to acquire a non-recursive mutex:
#include <pthread.h>
class Lock
{
public:
Lock( pthread_mutex_t& mutex )
: mutex_( mutex )
{
pthread_mutex_lock( &mutex_ );
}
~Lock()
{
pthread_mutex_unlock( &mutex_ );
}
private:
pthread_mutex_t& mutex_;
};
class Foo
{
public:
Foo()
{
pthread_mutex_init( &mutex_, NULL );
}
~Foo()
{
pthread_mutex_destroy( &mutex_ );
}
void hang()
{
Lock l( mutex_ );
subFunc();
}
void subFunc()
{
Lock l( mutex_ );
}
private:
pthread_mutex_t mutex_;
};
int main()
{
Foo f;
f.hang();
}
Is there a word or phrase for this situation? I'm not sure, but I don't think this can properly be called a deadlock: I'm of the understanding that a deadlock proper refers to the stalemate resulting from impassably ordered acquisition of multiple shared resources.
I've been anecdotally calling this a "single mutex deadlock" but I'd like to learn if there is a more proper term/phrase for this.
The Wikipedia article on reentrant mutexes cites Pattern-Oriented Software Architecture, which uses the term "self-deadlock." This term seems pretty reasonable to me!
...mutexes come in two basic flavors: recursive and non-recursive. A recursive mutex allows re-entrant locking, in which a thread that has already locked a mutex can lock it again and progress. Non-recursive mutexes, in contrast, cannot: a second lock in the same thread results in self-deadlock. Non-recursive mutexes can potentially be much faster to lock and unlock than recursive mutexes, but the risk of self-deadlock means that care must be taken when an object calls any methods on itself, either directly or via a callback, because double-locking will cause the thread to hang.
(emphasis added)
Various search results across a variety of technologies corroborate the use of this term.