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

1  #include <mutex>
2  #include <thread>
3  
4  const size_t maxThreads = 10;
5  std::mutex m2;
6  using namespace std;
7  
8  void do_work(size_t i, std::mutex *pm) {
9    std::lock_guard<std::mutex> lk(*pm);
10   //printf("hello");
11   // Access data protected by the lock.
12 }
13 
14 void start_threads1() {
15   std::thread threads[maxThreads];
16   std::mutex m1;
17 
18   for (size_t i = 0; i < maxThreads; ++i) {
19     threads[i] = std::thread(do_work, i, &m1); // Uncompliant code. If you use mutex 'm1' to start
20   }                                            // several threads, when one thread ends, this mutex
21 }                                              // will be destroyed while other threads 
22                                                // are still locking this mutex.
23 void start_threads2() {
24   std::thread threads[maxThreads];
25 
26   for (size_t i = 0; i < maxThreads; ++i) {
27     threads[i] = std::thread(do_work, i, &m2); //compliant code, by using global mutex variable.
28   }
29 }
30 
31 void run_threads() {
32   std::thread threads[maxThreads];
33   std::mutex m3;
34 
35   for (size_t i = 0; i < maxThreads; ++i) {
36     threads[i] = std::thread(do_work, i, &m3);
37   }
38 
39   for (size_t i = 0; i < maxThreads; ++i) {
40     threads[i].join();                         // compliant code, by using join method.
41   }
42 }