Why program hangs when threads detached - c++

I wrote this code to test some behaviour of boost asio together with detached threads.
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <string>
#include <thread>
class printer {
public:
printer(boost::asio::io_service &io)
: timer_(io, boost::posix_time::seconds(1)), count_(0) {
timer_.async_wait(boost::bind(&printer::print, this));
}
~printer() { std::cout << "Final count is " << count_ << "\n"; }
void print() {
if (count_ < 10) {
std::cout << "thread " << std::this_thread::get_id()
<< ", count = " << count_ << std::endl;
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this));
}
}
private:
boost::asio::deadline_timer timer_;
int count_;
};
boost::asio::io_service io;
int main() {
boost::asio::io_service::work work(io);
std::cout << "main thread " << std::this_thread::get_id() << std::endl;
std::thread t([] { io.run(); });
std::thread t2([] { io.run(); });
t.detach();
t2.detach();
printer p(io);
std::string name;
std::cout << "Press a key";
std::getline(std::cin, name);
std::cout << "finished" << std::endl;
return 0;
}
I wanted to see what happens when I have two worker threads, running io_service.run method, and what happens when they are detached (especially what happens when program exits).
The first problem is that when I run this program on linux I can see only one thread id when in Printer. Somehow the second thread does not take the task from io_service, even though it should, as it is running io_service.run method.
The second problem I see is that sometimes when I press ENTER before all 10 printouts from Printer are made, the program exits normally, and sometimes not (console hangs). Why is that?
What am I doing wrong here?

The main problem in your code is that the printer get called even after its destruction: the threads are detached, so they might be running even when the main function is ended and the printer is destroyed. With this issue it is not possible to have a defined behaviour, since the threads still might work with the printer that is destroyed. The hanging sometimes happens sometimes not - undefined behavior. Why this happens hard to say specifically. What is obvious here is that the threads are working with garbage data.
Summing up the flaws:
There is a possibility for the printer instance to be used even after destruction;
There is a possibility for the io_service instance to be used even after destruction: the threads' labmdas are holding references and the run method might still be in the process of execution while the objects are destroyed (there is no any guaranties on the relative order of static variable destruction and the detached thread terminations, as well as boost::asio::io_service does not block the destructor for the run method to be finished).
My suggestion is to introduced a defined order of destruction. Unfortunately, you cannot just say: ok, I am done, threads are detached, I quit. Because there is still work going on in the threads, but the relevant objects are destroyed.
class printer {
public:
printer(boost::asio::io_service& io)
: timer_(io, boost::posix_time::seconds(1)), count_(0) {
timer_.async_wait(
boost::bind(&printer::print, this));
}
~printer() { std::cout << "Final count is " << count_ << "\n"; }
void print() {
if (count_ < 10) {
std::cout << "thread " << std::this_thread::get_id() << ", count = " << count_
<< std::endl;
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(
boost::bind(&printer::print, this));
}
}
boost::asio::deadline_timer timer_;
int count_;
};
boost::asio::io_service io;
int main() {
auto work = std::unique_ptr<boost::asio::io_service::work>(
new boost::asio::io_service::work(io));
std::cout << "main thread " << std::this_thread::get_id() << std::endl;
std::thread t([&] { io.run(); });
std::thread t2([&] { io.run(); });
printer p(io);
std::string name;
std::cout << "Press a key";
std::getline(std::cin, name);
work.reset();
io.stop();
t.join();
t2.join();
std::cout << "finished" << std::endl;
return 0;
}

The result of the program depends on the order in which the two detached threads are executed. It's possible that sometimes they both start running after the main program has finished, and therefore the io object has already been destroyed.
You should try to force them to run before the main program exits, either by making them joinable or, if you really want to try them as detached, by adding a sleep before the program exits.

Related

Executing a non blocking thread in C++

I have a main program, this main program executes a thread that perform an action until the user triggers a stop. The problem that I have is if I add th.join() the main program won't continue until the thread finishes. And If there is no .join() the program crashs.
#include <iostream>
#include <thread>
#include <optional>
static bool s_finished = false;
using namespace std::literals::chrono_literals;
void SendData(int id)
{
std::cout << "Working thread: " << id << std::endl;
std::cout << "Started thread id: " << std::this_thread::get_id() << std::endl;
while (!s_finished)
{
std::cout << "Working\n";
std::this_thread::sleep_for(1s);
}
}
void startRecording(std::optional<int> t)
{
std::thread th1 (SendData, 1);
//th1.join();
std::cout << "[startRecording] Other Task" << std::endl;
}
void stopRecording()
{
s_finished = true;
std::cout << "[stopRecording] Other Task" << std::endl;
}
int main()
{
std::cout << "Start Program!" << std::endl;
startRecording();
std::this_thread::sleep_for(5s);
stopRecording();
return 0;
}
How can I do this?
Joining a thread will cause the program to stop until that thread is finished, and that's why the program blocks. We have to call join() eventually so that all child threads finish before the program exits, but we shouldn't call join until we need the child thread to be finished.
The simplest way to get the program to work is to return the thread from startRecording, so that we have control of it inside main. Then, we join the thread at the end of main, after we call stopRecording.
#include <iostream>
#include <thread>
#include <optional>
#include <atomic>
// (1) This needs to be atomic to avoid data races
std::atomic<bool> s_finished { false };
using namespace std::literals::chrono_literals;
void SendData(int id)
{
std::cout << "Working thread: " << id << std::endl;
std::cout << "Started thread id: " << std::this_thread::get_id() << std::endl;
while (!s_finished)
{
std::cout << "Working\n";
std::this_thread::sleep_for(1s);
}
}
std::thread startRecording(std::optional<int> t)
{
std::thread th1 (SendData, 1);
std::cout << "[startRecording] Other Task" << std::endl;
// (2) We return the thread so we can join it in main:
return th1;
}
void stopRecording()
{
s_finished = true;
std::cout << "[stopRecording] Other Task" << std::endl;
}
int main()
{
std::cout << "Start Program!" << std::endl;
// (3) We save the thread to a variable named 'worker'
// so we can join it later. I also added an input to startRecording b/c it needed one
std::thread worker = startRecording(std::optional<int>{1});
std::this_thread::sleep_for(5s);
stopRecording();
// (4) Join here, at the end
worker.join();
return 0;
}
Now, the program prints the expected output, then exits without problems:
Start Program!
[startRecording] Other Task
Working thread: 1
Started thread id: 139985258444544
Working
Working
Working
Working
Working
[stopRecording] Other Task
I marked my changes with (1), (2), (3), and (4) in the comments of the code. They're pretty small, and if you have questions about any of them I can provide additional explanation!
Addendum - using global variables when the signature of startRecording can't be changed
In general, it's best to avoid global variables, but I know it's not always possible to do so. if startRecording's signature can't be changed, we can't return a thread, so the thread has to be accessed globally. Here's how to do that:
#include <iostream>
#include <thread>
#include <optional>
#include <atomic>
// (1) This needs to be atomic to avoid data races
std::atomic<bool> s_finished { false };
// (2) we initialize this in startRecording
std::thread worker;
using namespace std::literals::chrono_literals;
void SendData(int id)
{
std::cout << "Working thread: " << id << std::endl;
std::cout << "Started thread id: " << std::this_thread::get_id() << std::endl;
while (!s_finished)
{
std::cout << "Working\n";
std::this_thread::sleep_for(1s);
}
}
void startRecording(std::optional<int> t)
{
// (3) worker gets initialized, and thread starts
worker = std::thread(SendData, 1);
std::cout << "[startRecording] Other Task" << std::endl;
}
void stopRecording()
{
s_finished = true;
std::cout << "[stopRecording] Other Task" << std::endl;
}
int main()
{
std::cout << "Start Program!" << std::endl;
startRecording(std::optional<int>{1});
std::this_thread::sleep_for(5s);
stopRecording();
// (4) Join here, at the end
worker.join();
return 0;
}

boost signal and slot not working in different thread (using boost::asio::io_service)

I have written a small test program to understand the signal and slot mechanism provided by boost and their behavior when posted in different thread. I want to have slot's being called in different threads but the output of my program shows slots are not being called in different thread from which signal was emitted.
#include <iostream>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/random.hpp>
#include <boost/signals2.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/signals2/signal.hpp>
boost::signals2::signal<void (int)> randomNumberSig;
// ---------------- Thread 1 ----------------
boost::asio::io_service thread1_serv;
void handle_rnd_1(int number)
{
std::cout << "Thread1: " << boost::this_thread::get_id() << " & Number is " << number << std::endl;
}
void thread1_init(void)
{
std::cout << "Thread 1 Init" << std::endl;
boost::asio::io_service::work work (thread1_serv);
randomNumberSig.connect([] (int num) -> void {
std::cout << "Slot called from main thread" << std::endl;
thread1_serv.post(boost::bind(handle_rnd_1, num));
});
}
void thread1_loop(void)
{
}
void thread1(void)
{
thread1_init();
while (true) {
thread1_serv.run();
thread1_loop();
}
}
int main(int argc, char *argv[])
{
std::cout << "Starting the Program" << std::endl;
boost::thread t1(&thread1);
while (1) {
int num = 2;
std::cout << "Thread " << boost::this_thread::get_id() << " & Number: " << num << std::endl;
randomNumberSig(num);
boost::this_thread::sleep_for(boost::chrono::seconds(num));
}
return 0;
}
The output of the program is:
Starting the Program
Thread 7fae3a2ba3c0 & Number: 2
Thread 1 Init
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
I suspect post() method of the io_service is not working properly or I have missed something in initializing the io_service.
You don't handle invocation of run function properly.
You used work to prevent run from ending when there is no work to do.
But your work is local inside thread1_init so when this function ends, work
is destroyed and io_service::run exits when there are no handlers to be called.
After run finished, io_service is marked as stopped, and you need to call restart before
calling run (as subsequent invocation).
If you don't call restart, run returns immediately without processing any handlers - that is why you don't see them.
So first solution is to create work whose lifetime is the same as io_service (just use global variable - ugly):
boost::asio::io_service thread1_serv;
boost::asio::io_service::work work(thread1_serv);
Another solution, don't use work, just call restart before run:
thread1_init();
while (true) {
thread1_serv.restart();
thread1_serv.run();
thread1_loop();
}
Wandbox test

std::launch::async is blocking like a sync process

I am running Visual Studio 2012 and attempting to learn how std::async works. I have created a very simple C++ console application:
#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
std::cout << "foo() thread sleep" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "foo() thread awake" << std::endl;
}
int main()
{
std::future<void> res = std::async(std::launch::async, foo);
res.get();
std::cout << "MAIN THREAD" << std::endl;
system("pause");
return 0;
}
My initial expectation was to see "MAIN THREAD" printout appearing before "foo() thread awake" since the two threads are running asynchronously, with the foo() trailing behind due to its sleeping behavior. However, that is not what is actually happening. The call to res.get() blocks until foo() wakes up, and only then does it get to the "MAIN THREAD" printout. This is indicative of a synchronous behavior, so I am wondering what if perhaps I am either missing something, or not fully grasping the implementation. I have looked through numerous posts on this matter, but still cannot make any sense of it. Any help would be appreciated!
res.get();
blocks until the async is done.
http://en.cppreference.com/w/cpp/thread/future/get
Regardless of how you tell it to run, get can't give you the results until it's done.
Well, this is how std::future::get works - it blocks until future has some result or exception to provide.
that doesn't mean that async works synchronously, it is working asynchronously, it's only because you block the thread which waits on the result.
the idea was to to launch some task asynchronously, do something meanwhile and only call get when you need the result, as you might figured out, it is not the most scale-able thing..
if you use Visual Studio 2015, you can access the await keyword both for std::future and concurrency::task (Microsoft PPL library) , and for your own compatible defined types. this achieves non-blocking behavior.
#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
std::cout << "foo() thread sleep" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "foo() thread awake" << std::endl;
}
std::future<void> entry(){
await std::async(std::launch::async, foo);
std::cout << "foo has finished, back in entry()\n";
}
int main()
{
std::cout << "MAIN THREAD" << std::endl;
entry();
std::cout << "BACK INMAIN THREAD" << std::endl;
system("pause");
return 0;
} //make sure to compile with /await flag
The problem is that res.get() has to wait for its thread to finish before getting its result (if any). To see the concurrency in motion you need to move the get() to after the other code that you want to run at the same time.
This example may make it a little clearer:
#include <ctime>
#include <cstdlib>
#include <future>
#include <iostream>
void foo(int id) {
std::cout << "foo(" << id << ") thread sleep" << std::endl;
// random sleep
std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10));
std::cout << "foo(" << id << ") thread awake" << std::endl;
}
int main()
{
std::srand(std::time(0));
std::future<void> res1 = std::async(std::launch::async, foo, 1);
std::future<void> res2 = std::async(std::launch::async, foo, 2);
std::future<void> res3 = std::async(std::launch::async, foo, 3);
std::cout << "MAIN THREAD SLEEPING" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(20));
std::cout << "MAIN THREAD AWAKE" << std::endl;
// now wait for all the threads to end
res1.get();
res2.get();
res3.get();
system("pause");
return 0;
}

boost::asio::deadline_timer doesn't wake up (stress scenario)

I'm using a deadline_timer as an asynchronous event and I'm running into a situation where, after some time, the thread waiting on the event never seems to be woken up (despite more calls to cancel()). I've been able to reproduce this using some sample code that I've pasted below; it's not exactly consistent but I have seen what I think is the same issue I'm experiencing.
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
timer.expires_at(boost::posix_time::pos_infin);
int num_events = 0;
auto waiter = [&timer, &num_events](boost::asio::yield_context context) {
while (true) {
std::cout << "waiting on event" << std::endl;
boost::system::error_code e;
timer.async_wait(context[e]);
std::cout << "got event (" << e << ")" << std::endl;
++num_events;
}
};
boost::asio::spawn(io_service, std::move(waiter));
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
for (auto i = 0; i < 500000; ++i) {
timer.cancel();
std::cout << i << std::endl;
}
Am I doing something here that's unsupported and inadvertently hitting some race condition? The error code from the wait() never looks troublesome (even on the very last time it's woken up before it never seems to again). EDIT: I've also noticed the original bug on 3 different platforms (Windows, Mac and Linux) but the above test I've been using to reproduce has been on Windows.
The deadline_timer object is not threadsafe.
You're canceling it from another thread than the one that's posting the async_wait. This means the calls can race.
I'm not sure how this can completely inhibit the callback, in your sample. It seems to me that the program should /just/ quit because the tight loop to 500000 finishes quickly (doing many redundant cancels that never get processed, because the coroutine would e.g. not even have posted the new async_wait).
So maybe you mean, "why don't I get 500000 events".
UPDATE
After the comment, here's a trivial transformation that shows how you are gonna be fine calling members on the timer from within an actor. Note: this critically hinges on the idea that the io_service is run from a single thread only!
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
#include <iostream>
using boost::thread;
using boost::asio::io_service;
int main() {
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
timer.expires_at(boost::posix_time::pos_infin);
boost::atomic_bool shutdown(false);
int num_events = 0;
auto waiter = [&timer, &num_events, &shutdown](boost::asio::yield_context context) {
while (!shutdown) {
std::cout << "waiting on event" << std::endl;
boost::system::error_code e;
timer.async_wait(context[e]);
std::cout << "got event (" << e.message() << ")" << std::endl;
++num_events;
}
};
boost::asio::spawn(io_service, std::move(waiter));
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
for (auto i = 0; i < 5000; ++i) {
io_service.post([&timer, i]{
std::cout << i << std::endl;
timer.cancel();
});
}
io_service.post([&]{
shutdown = true;
timer.cancel();
});
thread.join();
std::cout << "Check: " << num_events << " events counted\n";
}
Also, it looks like you just wanted to signal a background task. As given you can simplify the program like:
See it Live On Coliru
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
using boost::thread;
using boost::asio::io_service;
int main() {
io_service svc;
int num_events = 0;
auto work = boost::make_shared<io_service::work>(svc); // keep svc running
boost::thread thread(boost::bind(&io_service::run, &svc));
for (auto i = 0; i < 500000; ++i) {
svc.post([&num_events,i]{
std::cout << "got event (" << i << ")" << std::endl;
++num_events;
});
}
work.reset();
thread.join();
std::cout << "Check: " << num_events << " events counted\n";
}
This does print all 500000 events:
got event (0)
got event (1)
got event (3)
...
got event (499998)
got event (499999)
Check: 500000 events counted

C++ Timer pausing execution of program until finished

C++, XCode 4.6.3, OSX 10.8.2, deploying on iOS
I am trying to create a timed event.
My thought process was to create a thread, do the timing in it and then at the end have it call another function. This is working however it is pausing the rest of the program.
//Launch a thread
std::thread t1(start_thread);
//Join the thread with the main thread
t1.join();
void start_thread()
{
std::cout << "thread started" << std::endl;
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_until(start + std::chrono::seconds(20));
stop_thread();
}
void stop_thread()
{
std::cout << "thread stopped." << std::endl;
}
Is there a way to do this that doesn't pause program execution?
Update:
I could declare the thread in the header file and join in the stop_thread():
void stop_thread()
{
std::cout << "thread stopped." << std::endl;
ti.join();
}
but that throws:
Type 'std::thread' does not provide a call operator
UPDATE 2: Calling t1.detach() instead of join seems to work.
You're right it works:
Here is an example coming from cpp reference
http://en.cppreference.com/w/cpp/thread/thread/detach
#include <iostream>
#include <chrono>
#include <thread>
void independentThread()
{
std::cout << "Starting concurrent thread.\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Exiting concurrent thread.\n";
}
void threadCaller()
{
std::cout << "Starting thread caller.\n";
std::thread t(independentThread);
t.detach();
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Exiting thread caller.\n";
}
int main()
{
threadCaller();
std::this_thread::sleep_for(std::chrono::seconds(5));
}
Output:
Starting thread caller.
Starting concurrent thread.
Exiting thread caller.
Exiting concurrent thread.
We see that the concurrent thread ends after the thread caller ends. This is not possible if detach is not called.
Hope that helps, but Jason found the solution.
Use a class instead.
enum{ PAUSED, STARTED, STOPPED };
class AsyncEvent
{
protected:
unsigned char mState;
public:
AsyncEvent():mState(PAUSED){ mThread = std::thread(&AsyncEvent::run,this); }
~AsyncEvent(){ mThread.join(); }
private:
std::thread mThread;
void run()
{
std::cout << "thread started" << std::endl;
while(mState != STOPPED)
{
if(mState == PAUSED)break;
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_until(start + std::chrono::seconds(20));
}
}
void stop()
{
mState = STOPPED;
}
void pause()
{
mState = PAUSED;
}
};