Main Content

CERT C++: CON54-CPP

Wrap functions that can spuriously wake up in a loop

Description

Rule Definition

Wrap functions that can spuriously wake up in a loop.1

Polyspace Implementation

The rule checker checks for Function that can spuriously wake up not wrapped in loop.

Examples

expand all

Issue

Function that can spuriously wake up not wrapped in loop occurs when the following wait-on-condition functions are called from outside a loop:

  • C functions:

    • cnd_wait()

    • cnd_timedwait()

  • POSIX functions:

    • pthread_cond_wait()

    • pthread_cond_timedwait()

  • C++ std::condition_variable and std::condition_variable_any class member functions:

    • wait()

    • wait_until()

    • wait_for()

Wait-on-condition functions pause the execution of the calling thread when a specified condition is met. The thread wakes up and resumes once another thread notifies it with cnd_broadcast() or an equivalent function. The wake-up notification can be spurious or malicious.

Risk

If a thread receives a spurious wake-up notification and the condition of the wait-on-condition function is not checked, the thread can wake up prematurely. The wake-up can cause unexpected control flow, indefinite blocking of other threads, or denial of service.

Fix

Wrap wait-on-condition functions that can wake up spuriously in a loop. The loop checks the wake-up condition after a possible spurious wake-up notification.

Example - std::condition_variable::wait Not Wrapped in Loop
#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
	}
}

In this example, the thread uses std::condition_variable::wait to pause execution when input is greater than THRESHOLD. The paused thread can resume if another thread uses std::condition_variable::notify_all, which notifies all the threads. This notification causes the thread to wake up even if the pause condition is still true.

Correction — Wrap std::condition_variable::wait in a while Loop Explicitly

One possible correction is to wrap the call to std::condition_variable::wait in a while loop. The loop checks the pause condition after the thread receives a possible spurious wake-up notification.

#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);
	}
}

Correction — Wrap std::condition_variable::wait in a Loop Implicitly

The std::condition_variable::wait function has an overload that accepts a lambda function as a second argument. The predicate of the Lambda function indicates when it is safe to stop waiting and proceed with the code execution. This overload of the std::condition_variable::wait function behaves as if it is implicitly wrapped in a loop. In this code, the functionstd::condition_variable::wait is invoked by using a Lambda function. Here, unwanted waking of the thread is prevented because the thread wakes up when the predicate of the Lambda function is 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); });
	
}

Check Information

Group: 10. Concurrency (CON)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.