How to stop C++ program from crashing when closing while a condition_variable is waiting?

0

I am building a multi-threaded server for my project.
I am using condition variables and locks.
I have the condition variable cv as global and the mutex _mtxReceivedMessages as a class member.

This is the function that waits for the user message:

void Server::handleReceivedMessages()
{
 while (1)
 {
    std::unique_lock<std::mutex> lck(_mtxReceivedMessages);
    while (_queRcvMessages.size() == 0) cv.wait(lck); // As long as there are 0 messages in the queue
 }
}

This is the function that calls the notifies the cv:

void Server::addReceivedMessage(ReceivedMessage* msg)
{
    _queRcvMessages.push(msg); // Adds the message to the queue
    cv.notify_all(); // Unlockes all locked functions
}

The Problem is that if I try to close the program while the function handleReceivedMessages is waiting (before the function addReceivedMessage was called) the program crashes,
but if I remove the line:

 while (_queRcvMessages.size() == 0) cv.wait(lck); // As long as there are 0 messages in the queue

The program exits just fine.

The program crashes with: Unhandled exception at 0x7748507C (ntdll.dll) in Nuvola.exe: 0xC000000D: An invalid parameter was passed to a service or function.

What can be the problem ?

c++
multithreading
mutex
condition-variable
asked on Stack Overflow Nov 21, 2017 by shaked nissanov

1 Answer

5

If you want clean shutdown, you need to design it into everything. Your server needs a shutdown function (which can be its destructor). And your handleReceivedMessages function needs a way to stop on shutdown.

For example, you could add a bool shutdown; to your Server class. To shut the class down, acquire the mutex, set shutdown to true, and signal the condition variable. (You may need to join the server's thread if it has one.)

Your handleReceivedMessages function would then look more like this:

void Server::handleReceivedMessages()
{
 while (1)
 {
    std::unique_lock<std::mutex> lck(_mtxReceivedMessages);
    while (!shutdown && _queRcvMessages.size() == 0) cv.wait(lck); // As long as there are 0 messages in the queue
    if (shutdown) return;
 }
}
answered on Stack Overflow Nov 21, 2017 by David Schwartz

User contributions licensed under CC BY-SA 3.0