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
Related
Let's say we have two running threads that both would throw exceptions and there are exception handlers in these threads.
Would C++ be able to handle that, not running into terminated or undefined behavior.
Is it correct that exception belongs to per thread, and each thread can have no more than one exception at a time?
Is it correct that exception belongs to per thread
That is correct.
and each thread can have no more than one exception at a time?
A thread can have more than one active exception. See int uncaught_exceptions() noexcept:
Detects how many exceptions in the current thread have been thrown or rethrown and not yet entered their matching catch clauses.
E.g.:
#include <iostream>
#include <stdexcept>
void f() {
throw std::runtime_error("error");
}
struct A {
~A() {
std::cout << "uncaught_exceptions: " << std::uncaught_exceptions() << '\n';
}
};
struct B {
~B() {
try {
A a;
f();
}
catch(std::exception&) {}
}
};
int main() {
try {
B b;
f();
}
catch(std::exception&) {}
}
Outputs:
uncaught_exceptions: 2
The following example shows that the exception handler is using the stack of thread t1 which made a division by zero exception. It means that exception belongs to per thread.
// g++ -std=c++0x -pthread -fnon-call-exceptions main.cpp
#include <iostream>
#include <thread>
#include <signal.h>
void handler(int signo) {
int handler_local_var;
std::cout << &handler_local_var << " in stack of handler" << std::endl;
throw signo;
}
void thread1(std::string msg) {
int t1_local_var;
std::cout << &t1_local_var << " in stack of " << msg << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
signal(SIGFPE,handler);
try {
int x = 100 / 0; /* ignore warning: division by zero [-Wdiv-by-zero] */
}
catch (...) {
std::cout << "caught" << std::endl;
}
while (1) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
void thread2(std::string msg) {
int t2_local_var;
std::cout << &t2_local_var << " in stack of " << msg << std::endl;
while (1) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
int main() {
int main_local_var;
std::cout << &main_local_var << " in stack of main" << std::endl;
std::thread t1(thread1,"t1");
std::thread t2(thread2,"t2");
while (1) {
std::this_thread::sleep_for(std::chrono::seconds(2)); /* Ctrl-C to stop */
}
return 0;
}
Test result:
$ ./a.out
0x7ffee7fea788 in stack of main
0x7f0b54b92d68 in stack of t2
0x7f0b55393d54 in stack of t1
0x7f0b55393754 in stack of handler
caught
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
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().
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
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.