Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting a mutex that is locked

Tags:

c++

mutex

I have a program with multiple resources that needs to be lock by their own mutex.

In this program, it might happen that while mutex for resource A is locked, resource A is deleted in another thread.

The following code try to reproduce the logic of what I try to accomplish :

#include <thread>
#include <mutex>
#include <iostream>
#include <map>
int g_i = 0;
struct Resource
{
    std::mutex* m_mutex;
};

std::map<unsigned int, Resource> myResources;

std::mutex g_i_mutex;  // protects g_i

void shutdown()
{
    std::cout << "shutdown -> myMap.size = : " << myResources.size() << std::endl;
    std::lock_guard<std::mutex> lock(*myResources[1].m_mutex);
    ++g_i;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    delete myResources[1].m_mutex;
    myResources[1].m_mutex = NULL;
    myResources.erase(1);
    std::cout << "shutdown -> myMap.size = : " << myResources.size() << std::endl;
    std::cout << "shutdown : " << g_i << '\n';


}

 void onRecognize()
{
    std::cout << "onRecognize -> myMap.size = : " << myResources.size() << std::endl;
    std::lock_guard<std::mutex> lock(*myResources[1].m_mutex);
    std::cout << "onRecognize -> myMap.size = : " << myResources.size() << std::endl;
    ++g_i;

    std::cout <<  "onRecognize : " << g_i << '\n';


}

int main()
{
    std::cout << __func__ << ": " << g_i << '\n';
    Resource myStruct;
    myStruct.m_mutex = new std::mutex();
    myResources[1] = myStruct;
    std::thread t1(shutdown);
    std::thread t2(onRecognize);

    t1.join();
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    t2.join();

    std::cout << __func__ << ": " << g_i << '\n';
}

I tried this snippet of code and it works. But I am wondering what happen with lock_guard in onRecognize function, because the mutex is being deleted while he is locked. So, my question might be :

Does deleting a mutex while he is locked somewhere else is dangerous?

Thx

like image 964
peterphonic Avatar asked Dec 01 '15 21:12

peterphonic


2 Answers

Don't destroy a mutex while it is locked.

The behavior is undefined if the mutex is owned by any thread or if any thread terminates while holding any ownership of the mutex.

http://en.cppreference.com/w/cpp/thread/mutex/~mutex

like image 132
Brian Bi Avatar answered Sep 30 '22 16:09

Brian Bi


You have a fundamental concurrency error that renders your code unreliable. The pointer m_mutex is modified in one thread and used in another, and no synchronization of any kind protects it.

This is catastrophic even if you can't imagine a way it can fail. But it happens to be very easy to imagine ways it can fail. Consider:

  1. onRecognize evaluates *myResources[1].m_mutex but hasn't constructed the lock guard yet.
  2. shutdown acquires the lock, destroys the mutex, and returns.
  3. onRecognize tries to construct the lock guard on a lock that no longer exists.
  4. Boom.

So you have bigger problems than anything specific to the semantics of mutexes.

like image 28
David Schwartz Avatar answered Sep 30 '22 16:09

David Schwartz