boost disable_interruption not preventing thread_interrupted - c++

I am trying to prevent interruption of a thread while it is in a particular scope. However, using boost::this_thread::disable_interruption di() does not seem to have any effect.
#include <boost/thread.hpp>
#include <iostream>
void worker() {
std::cout << "START" << std::endl;
for(;;) {
{
boost::this_thread::disable_interruption di();
try {
boost::this_thread::sleep(boost::posix_time::seconds(1));
}
catch(boost::thread_interrupted & e) {
assert( false );
}
}
try {
boost::this_thread::interruption_point();
}
catch(boost::thread_interrupted & e) {
break;
}
}
std::cout << "END" << std::endl;
}
int main() {
boost::thread thread(&worker);
thread.interrupt();
thread.join();
}
The documentation appears to imply that boost::this_thread::sleep() will not throw boost::thread_interrupted while di is in scope.
What am I doing wrong?

You should remove parenthesis in the following line:
//boost::this_thread::disable_interruption di();
boost::this_thread::disable_interruption di;
Instead of creating disable_interruption object, you declared function di.

Related

Crash when calling interrupt() on a boost::thread, which has another boost::thread

I'm getting a crash when calling interrupt() on an outer boost::thread, which runs an inner boost::thread, which is connected to a thread_guard. It's not crashing when calling join() manually on the inner thread.
Crash:
terminate called after throwing an instance of 'boost::thread_interrupted'
Source:
https://gist.github.com/elsamuko/6e178c37fa2cf8742cb6bf512f2ff866
#include <iostream>
#include <thread>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([]{
while(true) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
LOG("Interrupting inner");
boost::thread_guard<boost::join_if_joinable> guard(inner); // crashes
// inner.join(); // works
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main(int argc, char* argv[]) {
LOG("Start");
double_interrupt();
LOG("End");
return 0;
}
Compile & Run:
http://coliru.stacked-crooked.com/a/46c512bf9a385fff
I'm running on Ubuntu 18.04. with g++ 7.5.0 and got the latest boost 1.78.0.
I opened this issue on github, too: https://github.com/boostorg/thread/issues/366
You're mixing std::thread and boost::thread.
Only Boost Thread knows about interruption points. Use that to fix:
Live On Coliru
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while (true) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
}
});
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
std::cout << "Interrupting inner" << std::endl;
boost::thread_guard<boost::join_if_joinable> guard(inner);
}
});
std::cout << "Interrupting outer" << std::endl;
outer.interrupt();
outer.join();
}
int main() {
std::cout << "Start" << std::endl;
double_interrupt();
std::cout << "End" << std::endl;
}
Prints
Start
Interrupting outer
End
I got a solution. The problem was, that the join() of the thread_guard waits for the inner thread with a condition_variable::wait(). condition_variable::wait() itself checks, if it's interruptible and throws an exception.
The solution is to use a custom thread_guard with disable_interruption:
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void work() {
size_t sum = 0;
for(int i = 0; i < 1E7; ++i) { sum += 1; }
LOG("work: " << sum);
}
// helper struct to interrupt a boost::thread within a boost::thread
struct non_interruptable_interrupt_and_join_if_joinable {
template <class Thread>
void operator()(Thread& t) {
if(t.joinable()) {
boost::this_thread::disable_interruption di;
t.interrupt();
t.join();
}
}
};
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while(true) {
boost::this_thread::interruption_point();
work();
}
});
{
boost::thread_guard<non_interruptable_interrupt_and_join_if_joinable> guard(inner);
LOG("Interrupting inner");
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main() {
LOG("Start");
double_interrupt();
LOG("End");
}
Run here:
http://coliru.stacked-crooked.com/a/a365e40a2bd574cc

Exit program when catch exception from thread

Referring to Catching exception from worker thread in the main thread, I created a worker thread that throws exception to main thread and then terminates the program (the logic is to exit program upon exception happens).
I didn't seems to be implementing it correctly, as the program won't execute till the line where exit() was called.
Sample code:
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while(shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
try
{
workerThread.run();
}
catch (...)
{
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
}
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
}
return 0;
}
What did i miss ? Is the current approach correct ? If no, how do i do it correctly ? thanks
In the code you posted, the exception check is happening only once, and possibly before the thread has been launched.
Also you're catching an error from the host thread but the error you're throwing is on the second thread.
I fixed these issues, by waiting for the second thread to finish before checking the exception.
Anyways, the paradigmatic way to throw an exception across a thread can be found here: How can I propagate exceptions between threads?
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
//thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
workerThread.run();
workerThread.thread.join();
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
}
return 0;
}
Exception should be caught at the for loop instead of workerThread.run(), since run() will exit immediately.
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
{
std::thread thread;
void doSomething()
{
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
{
try
{
shouldStop = true;
throw std::runtime_error("something really bad happened");
}
catch (const std::runtime_error &ex)
{
_exceptionPtr = std::current_exception();
}
}
}
}
void run()
{
thread = std::thread([this] { doSomething(); });
thread.detach();
}
};
int main(int argc, char *argv[])
{
WorkerThread workerThread;
workerThread.run();
for (;;)
{
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
if (_exceptionPtr)
{
try
{
std::rethrow_exception(_exceptionPtr);
}
catch (std::runtime_error &ex)
{
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
}
}
}
return 0;
}
Credits to #liliscent

std::async and std::shared_future causes the program to fall

I am trying to run some function in asynchronous manner. For this purpose I wrote class called Core where I use std::async to run function in different thread and std::shared_future<int> to wait for this thread and possibly to get future result. This is code of test program:
#include <iostream>
#include <future>
class Core : public std::enable_shared_from_this<Core>
{
public:
Core()
: isRunning_(false) {
};
~Core() {
isRunning_ = false;
if (f_.valid())
{
f_.wait();
std::cout << "Result is: " << f_.get() << std::endl;
}
};
void Start() {
isRunning_ = true;
auto self(shared_from_this());
f_ = std::async(std::launch::async, [self, this]() {
try {
while (true) {
if (!isRunning_)
break;
std::cout << "Boom" << std::endl; // Error occurs here
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
catch (const std::exception& e) {
std::cerr << "Loop error:" << e.what();
}
return 999;
});
}
private:
std::shared_future<int> f_;
std::atomic<bool> isRunning_;
};
int main()
{
try {
std::shared_ptr<Core> load(new Core);
load->Start();
throw std::runtime_error("Generate error"); // Added in order to generate error
}
catch (const std::exception& e) {
std::cout << "Error occurred: " << e.what();
}
return 0;
}
Each time when I start this program it crashes at this line:
std::cout << "Boom" << std::endl; // Error occurs here
with this error:
That is debugger error and call stack which I managed to get during debugging:
Looks like Core destructor function doesn't call at all. Why is it happens? weird!!!
Could you tell me where is my mistake? Thanks.
When main thread returns from main() it starts tearing down the environment before terminating the whole process. All this while background thread is accessing objects there are being destroyed or have been destroyed already.
I am not sure what you are triying to achieve, but you are doing something wrong:
Your lambda should execute some work and return immediately after it is done e.g. you should never loop forever.
Your main thread should wait for your future to complete by calling std::future<T>::get().

Boost interrupted exception not caught in MAC environment [duplicate]

I want to interrupt a thread using boost::thread interrupt(). I have the following code which doesn't throw boost::thread_interrupted& exception:
int myClass::myFunction (arg1, arg2) try{
//some code here
do {
boost::this_thread::interruption_point();
//some other code here
} while (counter != 20000);
}catch (boost::thread_interrupted&) {
cout << "interrupted" << endl;
}
If I replace boost::this_thread::interruption_point() with boost::this_thread::sleep( boost::posix_time::milliseconds(150)) exception is throw and interrupt works as it should.
Can someone explain why boost::this_thread::interruption_point() doesn't throw the expected exception?
As the commenter noted, there's no way to rule out a simple race condition (depends a lot on your architecture and load on the CPU). The fact adding an explicit sleep "helps" underlines this.
Are you running on a single-core system?
Here's a simple selfcontained example in case you spot something you are doing differently. See this simple tester:
#include <iostream>
#include <boost/thread.hpp>
struct myClass {
int myFunction(int arg1, int arg2);
};
int myClass::myFunction (int arg1, int arg2)
{
int counter = 0;
try
{
//some code here
do {
boost::this_thread::interruption_point();
//some other code here
++counter;
} while (counter != 20000);
} catch (boost::thread_interrupted&) {
std::cout << "interrupted" << std::endl;
}
return counter;
}
void treadf() {
myClass x;
std::cout << "Returned: " << x.myFunction(1,2) << "\n";
}
int main()
{
boost::thread t(treadf);
//t.interrupt(); // UNCOMMENT THIS LINE
t.join();
}
It prints
Returned: 20000
Or, if you uncomment the line with t.interrupt()
interrupted
Returned: 0
On my i7 system. See it Live On Coliru

boost::this_thread::interruption_point() doesn't throw boost::thread_interrupted& exception

I want to interrupt a thread using boost::thread interrupt(). I have the following code which doesn't throw boost::thread_interrupted& exception:
int myClass::myFunction (arg1, arg2) try{
//some code here
do {
boost::this_thread::interruption_point();
//some other code here
} while (counter != 20000);
}catch (boost::thread_interrupted&) {
cout << "interrupted" << endl;
}
If I replace boost::this_thread::interruption_point() with boost::this_thread::sleep( boost::posix_time::milliseconds(150)) exception is throw and interrupt works as it should.
Can someone explain why boost::this_thread::interruption_point() doesn't throw the expected exception?
As the commenter noted, there's no way to rule out a simple race condition (depends a lot on your architecture and load on the CPU). The fact adding an explicit sleep "helps" underlines this.
Are you running on a single-core system?
Here's a simple selfcontained example in case you spot something you are doing differently. See this simple tester:
#include <iostream>
#include <boost/thread.hpp>
struct myClass {
int myFunction(int arg1, int arg2);
};
int myClass::myFunction (int arg1, int arg2)
{
int counter = 0;
try
{
//some code here
do {
boost::this_thread::interruption_point();
//some other code here
++counter;
} while (counter != 20000);
} catch (boost::thread_interrupted&) {
std::cout << "interrupted" << std::endl;
}
return counter;
}
void treadf() {
myClass x;
std::cout << "Returned: " << x.myFunction(1,2) << "\n";
}
int main()
{
boost::thread t(treadf);
//t.interrupt(); // UNCOMMENT THIS LINE
t.join();
}
It prints
Returned: 20000
Or, if you uncomment the line with t.interrupt()
interrupted
Returned: 0
On my i7 system. See it Live On Coliru