exponenta event banner

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, который уведомляет все потоки. Это уведомление вызывает пробуждение потока даже в том случае, если условие паузы остается верным.

Коррекция - перенос 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 в цикле неявно

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

#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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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