CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED

Do not destroy a mutex while it is locked.

Mutex objects are used to protect shared data from being concurrently accessed. If a mutex object is destroyed while a thread is blocked waiting for the lock, critical sections and shared data are no longer protected. The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutex object.

Vulnerability and risk

Destroying a mutex while it is locked may result in invalid control flow and data corruption.

Mitigation and prevention

Do not destroy the mutex when it is locked.

Example

Copy
  #include <mutex>
  #include <thread>
  
  const size_t maxThreads = 10;
  std::mutex m2;
  using namespace std;
  
  void do_work(size_t i, std::mutex *pm) {
    std::lock_guard<std::mutex> lk(*pm);
   //printf("hello");
   // Access data protected by the lock.
 }
 
 void start_threads1() {
   std::thread threads[maxThreads];
   std::mutex m1;
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m1); // Uncompliant code. If you use mutex 'm1' to start
   }                                            // several threads, when one thread ends, this mutex
 }                                              // will be destroyed while other threads 
                                                // are still locking this mutex.
 void start_threads2() {
   std::thread threads[maxThreads];
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m2); //compliant code, by using global mutex variable.
   }
 }
 
 void run_threads() {
   std::thread threads[maxThreads];
   std::mutex m3;
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i] = std::thread(do_work, i, &m3);
   }
 
   for (size_t i = 0; i < maxThreads; ++i) {
     threads[i].join();                         // compliant code, by using join method.
   }
 }