Created
January 9, 2019 11:03
-
-
Save facontidavide/2315cd32ca39bd186083e004f0882a33 to your computer and use it in GitHub Desktop.
This simple multithreading C++ may sometimes crash (SIGSEGV) or remain blocked forever inside waitStart. Can you figure out why?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <thread> | |
#include <mutex> | |
#include <condition_variable> | |
#include <atomic> | |
// The purpose of the this apparently fine application is to make you appreciate thread santizers | |
// https://clang.llvm.org/docs/ThreadSanitizer.html | |
class Foo{ | |
public: | |
Foo(): _start_requested(false), _stop_requested(false), _thread( &Foo::loop, this ) | |
{} | |
void loop() | |
{ | |
while(!_stop_requested) | |
{ | |
waitStart(); | |
std::cout << "loop" << std::endl; | |
std::this_thread::sleep_for( std::chrono::milliseconds(200) ); | |
} | |
} | |
void waitStart() | |
{ | |
std::unique_lock<std::mutex> lock(_mutex); | |
while( !_start_requested ) | |
{ | |
_start_signaler.wait(lock); | |
} | |
} | |
void startLoop() | |
{ | |
std::unique_lock<std::mutex> lock(_mutex); | |
_start_requested = true; | |
_start_signaler.notify_all(); | |
} | |
void stopLoop() | |
{ | |
_stop_requested = true; | |
_thread.join(); | |
} | |
private: | |
std::atomic_bool _start_requested; | |
std::atomic_bool _stop_requested; | |
std::thread _thread; | |
std::mutex _mutex; | |
std::condition_variable _start_signaler; | |
}; | |
int main() | |
{ | |
Foo foo; | |
foo.startLoop(); | |
std::this_thread::sleep_for( std::chrono::seconds(1) ); | |
foo.stopLoop(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As class members are initialized in the order in which they are declared in the class, not the order in which they appear in the class initializer list, _thread is initialized before _mutex. When the thread procedure, loop(), is invocated, _mutex may Not have been initialized.