You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 6 Next »

Mutexes are used to protect shared data structures being concurrently accessed. If a mutex is destroyed while a thread is blocked waiting for that mutex, critical sections (shared data that would otherwise be protected from data races) are no longer protected.

The C++ Standard, [thread.mutex.class], paragraph 5 [ISO/IEC 14882-2014], states:

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.

This statement implies that destroying a mutex while a thread is waiting on it is undefined behavior.

Noncompliant Code Example

This noncompliant code example creates several threads that each invoke the do_work() function, passing a unique number as an ID.

#include <mutex>
#include <thread>

const size_t max_threads = 10;

void do_work(size_t i, std::mutex *lockp)
{
  std::lock_guard<std::mutex> guard(*lockp);

  // Access data protected by the lock.
}

void start_threads(void)
{
  std::thread threads[max_threads];
  std::mutex lock;

  for (size_t i = 0; i < max_threads; ++i) {
    threads[i] = std::thread(do_work, i, &lock);
  }
}

Compliant Solution

This compliant solution eliminates the race condition by extending the lifetime of the lock:

#include <mutex>
#include <thread>

const size_t max_threads = 10;

void do_work(size_t i, std::mutex *lockp)
{
  std::lock_guard<std::mutex> guard(*lockp);

  // Access data protected by the lock.
}

std::mutex lock;

void start_threads(void)
{
  std::thread threads[max_threads];

  for (size_t i = 0; i < max_threads; ++i) {
    threads[i] = std::thread(do_work, i, &lock);
  }
}

Compliant Solution

This compliant solution eliminates the race condition by joining the threads before the lock's destructor is invoked:

#include <mutex>
#include <thread>

const size_t max_threads = 10;

void do_work(size_t i, std::mutex *lockp)
{
  std::lock_guard<std::mutex> guard(*lockp);

  // Access data protected by the lock.
}
void run_threads(void)
{
  std::thread threads[max_threads];
  std::mutex lock;

  for (size_t i = 0; i < max_threads; ++i) {
    threads[i] = std::thread(do_work, i, &lock);
  }

  for (size_t i = 0; i < max_threads; ++i) {
    threads[i].join();
  }
}


Risk Assessment

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

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

CON50-CPP

Medium

Probable

High

P4

L3

Automated Detection

Tool

Version

Checker

Description

Fortify SCA

5.0

 

Can detect violations of this rule with CERT C Rule Pack

Parasoft C/C++test9.5BD-RES-FREE, BD-RES-INVFREE 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

MITRE CWECWE-667, Improper Locking

Bibliography

[ISO/IEC 9899:2011]7.26.4.1, "The mtx_destroy Function"

 


  • No labels