CERT C++: CON54-CPP

Оберните функции, которые могут ложно проснуться в цикле

Описание

Определение правила

Оберните функции, которые могут ложно проснуться в цикле.[1]

Реализация Polyspace

Эта проверка проверяет Функцию, которая может ложно проснуться, не завернутая в цикл.

Примеры

расширить все

Проблема

Функция, которая может ложно проснуться, не обернутая в цикл, возникает, когда следующие функции ожидания условия вызываются из-за пределов цикла:

  • Функции C:

    • cnd_wait()

    • cnd_timedwait()

  • Функции POSIX:

    • pthread_cond_wait()

    • pthread_cond_timedwait()

  • C++ std::condition_variable и std::condition_variable_any функции члена класса:

    • wait()

    • wait_until()

    • wait_for()

Функции ожидания зависят от выполнения вызывающего потока при выполнении заданного условия. Поток просыпается и возобновляется, когда другой поток уведомляет его с cnd_broadcast() или эквивалентную функцию. Уведомление о пробуждении может быть ложным или вредоносным.

Риск

Если поток получает ложное уведомление о пробуждении и условие функции ожидания не проверяется, поток может проснуться преждевременно. Пробуждение может вызвать неожиданный поток управления, неопределенную блокировку других потоков или отказ в обслуживании.

Зафиксировать

Оберните функции ожидания при условии, которые могут ложно проснуться в цикле. Цикл проверяет условие пробуждения после возможного ложного уведомления о пробуждении.

Пример - std::condition_variable::wait Не обернутый в цикл
#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>

#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	// test condition to pause thread 
	if (input > THRESHOLD) {
	//pause current thread
		cv.wait(lk);//Noncompliant
	}
}

В этом примере поток использует std::condition_variable::wait для паузы выполнения при input больше THRESHOLD. Приостановленный поток может возобновиться, если другой поток использует std::condition_variable::notify_all, который уведомляет все потоки. Это уведомление заставляет поток просыпаться, даже если условие паузы все еще соответствует true.

Коррекция - Обернуть std::condition_variable::wait в while Цикл явно

Одной из возможных коррекций является перенос вызова в std::condition_variable::wait в while цикл. Цикл проверяет условие паузы после получения потоком возможного ложного уведомления о пробуждении.

#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>

#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	// test condition to pause thread 
	while (input > THRESHOLD) {
	//pause current thread
		cv.wait(lk);
	}
}

Коррекция - Обернуть std::condition_variable::wait в цикле неявно

The std::condition_variable::wait функция имеет перегрузку, которая принимает лямбда-функцию как второй аргумент. Предикат функции Lambda указывает, когда безопасно остановить ожидание и продолжить выполнение кода. Эта перегрузка std::condition_variable::wait функция ведет себя так, как если бы она была неявно завёрнута в цикл. В этом коде функция std::condition_variable::wait вызывается с помощью функции Lambda. Здесь нежелательное пробуждение потока предотвращается, потому что поток просыпается, когда предикат функции Lambda равен true.

#include <stdio.h>
#include <stdio.h>
#include <stddef.h>
#include <thread>
#include <mutex>
#define THRESHOLD 100

std::mutex myMutex;
std::condition_variable cv;

void func(int input)
{
	std::unique_lock<std::mutex> lk(myMutex);
	cv.wait(lk,[&input]{ return !(input>THRESHOLD); });
	
}

Проверяйте информацию

Группа: 10. Параллелизм (CON)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.