I'm in the process of rewriting legacy code based on an old Framework with C++11 using thread and chrono libraries. To summarize the library spawns a thread and waits either an event or a delay.
I've written a code sample that works well until I strip the .gnu.version
section.
1. Compilation
g++ -std=c++11 test.cpp -o test -pthread -lpthread
2. Execution before strip
$ ./test
>>run()
run() - before wait()
>>wait()
< wait()
run() - after wait()
run() - before wait_until()
run() - after wait_until()
run() - before wait()
run() - after wait()
< run()
3. Strip .gnu.version section
strip -R .gnu.version test
4. Execution after strip
./test
>>run()
run() - before wait()
>>wait()
< wait()
run() - after wait()
run() - before wait_until()
Segmentation fault (core dumped)
From what I was able to investigate the segfault occurs in std::condition_variable::.wait_until()
when calling the undelaying pthread library.
Here is the code sample :
#include <thread>
#include <iostream>
#include <condition_variable>
#include <unistd.h>
class Task
{
private:
std::mutex _mutex;
std::condition_variable _cv;
std::thread _thread;
bool _bStop;
bool _bWait;
void run()
{
std::unique_lock<std::mutex> lock(_mutex);
std::cout << ">>run()" << std::endl;
while (!_bStop)
{
if ( !_bWait )
{
std::cout << " run() - before wait()" << std::endl;
_cv.wait(lock);
std::cout << " run() - after wait()" << std::endl;
}
else
{
_bWait = false;
std::chrono::steady_clock::time_point ts = std::chrono::steady_clock::now()
+ std::chrono::seconds(1);
std::cout << " run() - before wait_until()" << std::endl;
_cv.wait_until(lock,ts);
std::cout << " run() - after wait_until()" << std::endl;
}
}
std::cout << "< run()" << std::endl;
}
public:
Task():_bStop(false),_bWait(false)
{
}
void start()
{
_thread = std::thread(&Task::run,this);
}
void wait()
{
std::cout << ">>wait()" << std::endl;
std::unique_lock<std::mutex> lock(_mutex);
_bWait = true;
_cv.notify_one();
std::cout << "< wait()" << std::endl;
}
void cancel()
{
std::unique_lock<std::mutex> lock(_mutex);
_bStop = true;
_cv.notify_one();
}
void join()
{
_thread.join();
}
};
int main()
{
Task t;
// Start Task thread
t.start();
// Sleeping here seems to help produce the error
usleep(10000);
t.wait();
// Wait for Task to process delay
sleep(5);
// Stop Task and wait for thread termination
t.cancel();
t.join();
return 0;
}
Aucun commentaire:
Enregistrer un commentaire