Boost Thread - How to acknowledge interrupt - c++

I have blocking task which will be performed by find_the_question() function. However, I do not want thread executing this function take more than 10 seconds. So in case it takes more than 10 seconds, I want to close that thread with cleaning all the resources.
I tried to write a code for that, but somehow I am not able to get a interrupt in find_the_question() function if thread takes more than 10 seconds. Could you please tell me what am I doing wrong?
void find_the_question(std::string value)
{
//allocate x resources
try{
//do some process on resources
sleep(14);
//clean resources
}
catch(boost::thread_interrupted const& )
{
//clean resources
std::cout << "Worker thread interrupted" << std::endl;
}
}
int main()
{
boost::posix_time::time_duration timeout = boost::posix_time::milliseconds(10000);
std::cout << "In main" << std::endl;
boost::thread t1(find_the_question, "Can you block me");
t1.interrupt();
if (t1.timed_join(timeout))
{
//finished
std::cout << "Worker thread finished" << std::endl;
}
else
{
//Not finished;
std::cout << "Worker thread not finished" << std::endl;
}
std::cout << "In main end" << std::endl;
}
Output:
If t1 takes more than 10 seconds to complete, I am getting following console output.
std::cout << "In main" << std::endl;
std::cout << "Worker thread not finished" << std::endl;
std::cout << "In main end" << std::endl;
whereas, I am expecting following output
std::cout << "In main" << std::endl;
std::cout << "Worker thread interrupted" << std::endl;
std::cout << "Worker thread not finished" << std::endl;
std::cout << "In main end" << std::endl;
Could you please tell me what am I doing wrong.
Thanks in advance

For using boost::thread::interrupt(), you have to use boost::thread::sleep() for it to work.
A running thread can be interrupted by invoking the interrupt() member
function of the corresponding boost::thread object. When the
interrupted thread next executes one of the specified interruption
points (or if it is currently blocked whilst executing one) with
interruption enabled, then a boost::thread_interrupted exception will
be thrown in the interrupted thread. If not caught, this will cause
the execution of the interrupted thread to terminate. As with any
other exception, the stack will be unwound, and destructors for
objects of automatic storage duration will be executed
Predefined interruption points:
The following functions are interruption points, which will throw
boost::thread_interrupted if interruption is enabled for the current
thread, and interruption is requested for the current thread:
boost::thread::join()
boost::thread::timed_join()
boost::condition_variable::wait()
boost::condition_variable::timed_wait()
boost::condition_variable_any::wait()
boost::condition_variable_any::timed_wait()
boost::thread::sleep()
boost::this_thread::sleep()
boost::this_thread::interruption_point()

Related

tbb::parallel_for_each not executing while canceling

I'm running tbb::parallel_for_each deep within a task_group. The task_group is being canceled and that seems to cause tbb::parallel_for_each to exit without satisfying its postcondition. Here's minimal test case:
tbb::task_group g;
std::vector<int> x { 0, 0, 0, 0 };
std::atomic<std::size_t> counter {0};
g.run([&x, &counter]() {
std::cout << "in run()\n" << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "in run(): slept\n" << std::flush;
assert(tbb::task::self().is_cancelled());
tbb::parallel_for_each(x, [&counter](int& y) {
std::cout << "in run(): in parallel_for_each\n" << std::flush;
++y;
++counter;
});
assert(counter == x.size());
});
std::cout << "canceling\n" << std::flush;
g.cancel();
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;
assert(g.is_canceling());
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;
g.wait();
std::cout << "canceled " << g.is_canceling() << " " << tbb::task::self().is_cancelled() << std::endl;
That is: It has tbb::task_group call run on a function that waits for 0.1 s, then loops over a vector. It counts how many iterations that loop does. It then cancel()s the task group. The output is
canceling
in run()
canceled 1 0
canceled 1 0
in run(): slept
Assertion failed: (counter == x.size()), function operator(), file test.cpp
That's to say that the inner loop never happens. My surprise, though, is that tbb::parallel_for_each is called and exits without exception, but its post-condition (of doing the loop) isn't met!
Is that the expected behavior? The docs don't give any caveats: https://software.intel.com/en-us/node/506160
How do I check for this behavior? Do I always have to check tbb::task::self().is_cancelled() after calling tbb::parallel_for_each if I want to be sure it actually did its job?
Shouldn't tbb::parallel_for_each throw an exception in this case (or at least return bool)?
I can "fix" this by using an isolated context (https://software.intel.com/en-us/node/506075) like this:
tbb::task_group_context root(tbb::task_group_context::isolated);
tbb::parallel_for_each(x, [&counter](int& y) {
std::cout << "in run(): in parallel_for_each\n" << std::flush;
++y;
++counter;
}, root);
but at the moment, I'm not sure when I can ever trust tbb::parallel_for_each to do its job.
Within a task group, calls to tbb::parallel_for_each are subordinate to the task group's context.
Cancelling that task group cancels it, and all subordinate task groups. I cannot find where in the docs "subordinate task group" is defined, but it appears to be groups under the group in the "task tree".
A cancelled tbb::parallel_for_each does not guarantee that all of its iterations are complete. No post condition was violated.
You cancelled the task group, which cancels the subordinate tbb::parallel_for_each's implicit task group, so it doesn't do the operations.
Your isolated context prevents the cancellation from propagating into the parallel for each's task group. You can replicate the effect in that code by canceling root prior to calling parallel_for_each.

Is there a way to explicitly destroy all handlers pending on a given boost::asio::io_context?

According to my knowledge and as far as I checked the boost::asio documentation and source code there is no way to destroy explicitly all pending handlers on a given io_context aside from destroying the context itself?
I need to be able, if possible, to stop the io_context, destroy the pending handlers on the io_context, then do some other things and finally destroy all io objects (timers, pipes, etc) associated with the given io_context and the io_context itself.
I know that I can use work_guard::reset and let all pending handlers to run and then the io_context will stop by itself, but the problem is that many of the handlers may produce (post/defer/etc) new pending handlers, etc i.e. each such handler will need to be guarded with something like 'if stopped'.
I think that the io_context::shutdown does exactly this but there is no way, aside from inheritance maybe, to call explicitly the shutdown function because it's not public.
Thanks.
Trying your suggestion using the protected shutdown results in a segfault on my system. I think it's protected for a reason :)
Anyhow, it looks like a judicious combination of restart/stop/reset might do the job. It's weird that some of the handler queue apparently stays around UNLESS one does a (empty) run/run_one. In fact even a poll_one seems to suffice. So, by all means, include that.
Here's my test bed code, you might find it useful:
Live On Coliru
#include <boost/asio.hpp>
#include <iostream>
using namespace std::chrono_literals;
struct Handler {
void operator()(boost::system::error_code ec) { std::cout << "Handler invoked: " << ec.message() << std::endl; }
struct Instance { // logging only unique instance to avoid noise of moved handlers
Instance() { std::cout << "Created handler instance" << std::endl; }
~Instance() { std::cout << "Destroyed handler instance" << std::endl; }
};
std::unique_ptr<Instance> _instance = std::make_unique<Instance>();
};
int main()
{
struct Hack : boost::asio::io_context {
using boost::asio::io_context::shutdown;
} io;
auto work = make_work_guard(io);
std::cout << " -- run" << std::endl;
auto t = std::thread([&]{ io.run(); });
{
boost::asio::high_resolution_timer tim(io, 2s);
tim.async_wait(Handler{});
work.reset(); // no longer needed
std::this_thread::sleep_for(500ms);
#if 1
io.stop();
#else
io.shutdown(); // segfaults
#endif
}
std::cout << " -- timer destructed" << std::endl;
std::cout << " -- joining" << std::endl;
t.join();
std::cout << " -- empy run to flush handler queue" << std::endl;
io.reset();
//io.run();
//io.run_one();
io.poll_one();
std::cout << " -- bye" << std::endl;
}
Prints
-- run
Created handler instance
-- timer destructed
-- joining
-- empy run to flush handler queue
Handler invoked: Operation canceled
Destroyed handler instance
-- bye
UPDATE
Here's my best suggestion (apart from, I guess, not sharing io at all):
Live On Coliru
#include <boost/asio.hpp>
#include <iostream>
using namespace std::chrono_literals;
struct Handler {
void operator()(boost::system::error_code ec) { std::cout << "Handler invoked: " << ec.message() << std::endl; }
struct Instance { // logging only unique instance to avoid noise of moved handlers
Instance() { std::cout << "Created handler instance" << std::endl; }
~Instance() { std::cout << "Destroyed handler instance" << std::endl; }
};
std::unique_ptr<Instance> _instance = std::make_unique<Instance>();
};
int main()
{
std::unique_ptr<boost::asio::io_context> io;
int i = 1;
for (auto delay : { 1500ms, 500ms }) {
std::cout << " ------------------- reinitialized -------------- \n";
io = std::make_unique<boost::asio::io_context>();
boost::asio::high_resolution_timer tim(*io, 1s);
std::cout << i << " -- run" << std::endl;
auto t = std::thread([&]{ io->run(); });
tim.async_wait(Handler{});
std::this_thread::sleep_for(delay);
std::cout << i << " -- stop" << std::endl;
io->stop();
std::cout << i << " -- joining" << std::endl;
t.join();
std::cout << " ------------------- destruct ------------------- \n";
io.reset();
}
std::cout << "Bye" << std::endl;
}
Prints
------------------- reinitialized --------------
1 -- run
Created handler instance
Handler invoked: Success
Destroyed handler instance
1 -- stop
1 -- joining
------------------- destruct -------------------
------------------- reinitialized --------------
1 -- run
Created handler instance
1 -- stop
1 -- joining
------------------- destruct -------------------
Destroyed handler instance
Bye

boost::scoped_lock appears not to lock std::cout

I'm using boost 1.54.0 and Visual Studio 2010. For the code:
#include <iostream>
#include "boost/thread/thread.hpp"
#include "boost/thread/mutex.hpp"
boost::mutex mx1;
void func1()
{
{
boost::mutex::scoped_lock(mx1);
std::cout << "Thread " << boost::this_thread::get_id() << " starting work." << std::endl;
}
int x = 0;
for (int i=0; i<100; i++)
x++;
{
boost::mutex::scoped_lock(mx1);
std::cout << "Thread " << boost::this_thread::get_id() << " finished." << std::endl;
}
}
int main(void)
{
boost::thread thread1(&func1);
boost::thread thread2(&func1);
thread1.join();
thread2.join();
return 0;
}
About half the time I get the following (with varying thread ids and execution order, obviously):
Thread Thread 15b0 starting work.
1a18 starting work.
Thread 15b0 finished.
Thread 1a18 finished.
...instead of this (which is what I'd expect):
Thread 15b0 starting work.
Thread 1a18 starting work.
Thread 15b0 finished.
Thread 1a18 finished.
However, using
mx1.lock();
std::cout << "Thread " << boost::this_thread::get_id() << " starting work." << std::endl;
mx1.unlock();
...seems to work with no problems.
The output always seems to follow the same pattern. Am I using the mutex incorrectly, or is it something to do with std::cout?
Replace
boost::mutex::scoped_lock(mx1);
with
boost::mutex::scoped_lock lock(mx1);
you fell a victim of the most frequently occurring typo with the scoped lock:-)

Create a child thread that is independent of parent in C++

I am working in a C++ DLL module where I need to perform a task for every X min independently. I tried to create a thread for the task but my main program which creates threads will also keep waiting for the child thread(s) to complete.
Could someone please help me how to create a separate process (Please provide sample code if possible) independent of main program and do the Task?
The process should take a function and run the code present in function for every X min.
EDIT:
void test(void *param)
{
cout << "In thread function" << endl;
Sleep(1000); // sleep for 1 second
cout << "Thread function ends" << endl;
_endthread();
}
int main()
{
HANDLE hThread;
cout << "Starting thread" << endl;
cout << (hThread = (HANDLE)_beginthread(test,0,NULL));
WaitForSingleObject( hThread, INFINITE );
cout << "Main ends" << endl;
return 0;
}
WaitForSingleObject() will block main until the thread completes. If you want to run some stuff periodically from the thread function test() you'll need to put a loop there. Best with some condition to trigger ending the thread function from main() when exiting. You shouldn't call WaitForSingleObject() before you want to exit the main() method. Thus you'll have the test() method running asynchonously.
bool endThread = false;
void test(void *param)
{
cout << "In thread function" << endl;
while(!endThread)
{
Sleep(1000); // sleep for 1 second
}
cout << "Thread function ends" << endl;
_endthread();
}
int main()
{
HANDLE hThread;
cout << "Starting thread" << endl;
cout << (hThread = (HANDLE)_beginthread(test,0,NULL));
// Do any other stuff without waiting for the thread to end
// ...
endThread = true;
WaitForSingleObject( hThread, INFINITE );
cout << "Main ends" << endl;
return 0;
}
Note that you might need to synchronize access to the endThread variable properly using a mutex or similar, the sample should just show the principle.
UPDATE:
In case you want to exit main() before the thread ends, you cannot use threads at all.
You'll need to create an independent child process as I had mentioned in my 1st comment. Lookup for the fork() and exec() functions to do this (there might be specific WinAPI methods for these also, I don't know about).

Running a boost thread as a Daemon

Is it possible to create a boost::thread and run it in the background (as a daemon)?
I am trying to the following but my thread dies when main exits.
/*
* Create a simple function which writes to the console as a background thread.
*/
void countDown(int counter) {
do {
cout << "[" << counter << "]" << endl;
boost::this_thread::sleep(seconds(1));
}while(counter-- > 0);
}
int main() {
boost::thread t(&countDown, 10);
if(t.joinable()) {
cout << "Detaching thread" << endl;
t.detach(); //detach it so it runs even after main exits.
}
cout << "Main thread sleeping for a while" << endl;
boost::this_thread::sleep(seconds(2));
cout << "Exiting main" << endl;
return 0;
}
[rajat#localhost threads]$ ./a.out
Detaching thread
Main thread sleeping for a while
[10]
[9]
Exiting main
[rajat#localhost threads]$
When your main() exits all other threads of the process are terminated (assuming Linux, can't say for Windows).
Why not just join() that background thread at the end of the main()? Or even better - use the main thread as the "daemon" thread?