Boost Thread - Create a Thread without join() - c++

I have an application that creates a thread, and it will be listening for incoming connections. And the main thread will be doing other things.
boost::mutex mutex;
void
ThreadFunction(int port, int(*callbackFunc)(int, int))
{
mutex.lock();
std::cout << "Cannot get to this point" << std::endl;
mutex.unlock();
Application app;
app.run(port, callbackFunc);
}
void
Init(int port, int(*callbackFunc)(int, int))
{
std::cout << callbackFunc(1,1) << std::endl;
boost::thread t(boost::bind(&ThreadFunction, port, callbackFunc));
}
int
main(){
int port = 2340;
Init(port, *callbackfunction);
return 0;
}
The problem I am having is that it never access the std::cout << "Cannot get to this point" << std::endl; However, if I call join() after I create the thread, it works just fine but then it is blocking the application.
What do I need to do for the thread call the ThreadFunction?

Your application terminates (by leaving main()) before the thread gets a chance to do its work. Once you implement a wait-for-connections loop, the problem will be resolved. So, no need to do anything.

Related

Thread.joinable return true even thread hasn't finished executing

std::mutex MTX;
bool ExitThread = false;
//This function is running in a separate thread
//for constantly trying to connect to a server in a non blocking manner
void ClientConnectingLoop(sf::TcpSocket* client, std::string ipAddress,
unsigned short port)
{
std::cout << "Start" << std::endl;
MTX.lock();
std::cout << "Start2" << std::endl;
while(client->connect(ipAddress, port) != sf::Socket::Status::Done &&
!ExitThread)
{
}
std::cout << "Done" << std::endl;
MTX.unlock();
}
int main()
{
//Code for setting ipaddress and port is abstracted.
std::string ipAddress;
unsigned short port;
//Setup socket
sf::TcpSocket clientSocket;
clientSocket.setBlocking(false);
//Connect to server
std::thread ClientConnectThread(ClientConnectingLoop, &clientSocket, ipAddress, port);
std::cout << "Connecting to server......" << std::endl;
//Wait until it finishes executing, code inside this loop is abstracted
while(!ClientConnectThread.joinable())
{
}
//The thread is finished executing.
if(ClientConnectThread.joinable())
{
std::cout << "Joinable returned true" << std::endl;
ClientConnectThread.join();
}
//........
}
The problem comes to that the thread returns joinable (true) despite the loop in the thread is still running.
So that means the console outputs "Connecting to server......" => "Start" => "Start2" => "Joinable returned true" but "Done" should be printed after "Start2" unless I misunderstood joinable function
I am still fairly new to c++ and SFML, please be kind when pointing out any mistakes.
Quoting directly from cppreference.com
std::thread::joinable
Checks if the thread object identifies an active thread of execution. Specifically, returns true if get_id() != std::thread::id(). So a default constructed thread is not joinable.
A thread that has finished executing code, but has not yet been joined is still considered an active thread of execution and is therefore joinable.
Based on this, the idea of a joinable thread is different. A thread is always joinable except if has been default-constructed and has not been assigned to a function/method to run or if you have already called the thread.join() method on it.
An rather simple solution to the problem at hand would be to use some multithreading-aware locking construct such as std::atomic or void futures to communicate the result as suggested in the Effective Modern C++ book of Scott Meyers

Execute callback function on main thread from std::thread

I have a requirement of executing a callback function on exit of a std::thread and the callback function should be executed on the main thread.
On thread creation I need to detach the thread and cannot block the main loop execution for thread completion.
i tried using std::signal but that does not seem to execute callback function on the main thread
#include <thread>
#include <csignal>
#include <iostream>
std::thread::id main_thread_id;
void func2()
{
for(int i = 0; i < 10000000; i++)
{
// do something
}
}
void func()
{
for(int i = 0; i < 10; i++)
{
func2();
}
std::raise(SIGUSR1);
}
void callback(int signal)
{
std::cout << "SIGNAL: " << signal << " THREAD ID:" <<
std::this_thread::get_id() << std::endl;
bool b = std::this_thread::get_id() == main_thread_id;
std::cout << "IS EXECUTED ON MAIN THREAD: " << b << std::endl;
}
int main()
{
main_thread_id = std::this_thread::get_id();
std::cout << "MAIN THREAD ID: " << std::this_thread::get_id() << std::endl;
std::signal(SIGUSR1, callback);
std::thread t1(func);
t1.detach();
for(int i = 0; i < 20; i++)
{
func2();
}
if(t1.joinable())
t1.join();
}
The result I get is that the callback function is not executed on main thread. Please suggest a way in which I can create a worker thread and call a callback function on main thread upon exit of the thread.
Thanks for the help
There are a few ways to do this.
First, your main thread could be running a message loop. In which case, you queue up a message with a payload that tells the main thread to run some code (either carry the code to run via a pointer part of the message to the main thread, or put it in some known spot that the main thread checks).
A second approach is to return something like a std::future<std::function<void()>> object, and the main thread checks if the future is ready. When it is ready, it runs the code.
A third approach is to create a concurrent queue that the main thread waits on, and stuff your message (containing code to run) onto that queue.
All of these things require the active cooperation of the main thread. The main thread cannot be preemted and told to run different code without its cooperation.
Which is best depends on features of your program you did not choose to mention in your question. If you are a graphical GUI with a message loop, use the message loop. If you are a streaming processor that paralellizes some work, and you don't need prompt execution, yet eventually will want to block on the parallel work, a future might be best. If you are a message passing channel-type app, a set of queues might be best.

boost::asio signal_set handler only executes after first signal is caught and ignores consecutive signals of the same type

I have a program and would like to stop it by sending SIGINT for writing some data to a file instead of exiting immediately. However, if the user of the program sends SIGINT again, then the program should quit immediately and forget about writing data to a file.
For portability reason I would like to use boost::asio for this purpose.
My initial (simplified) approach (see below) did not work. Is this not possible or am I missing something?
The handler seems to be called only once (printing out the message) and the program always stops when the loop has reached the max iteration number.
void handler(
const boost::system::error_code& error,
int signal_number) {
if (!error) {
static bool first = true;
if(first) {
std::cout << " A signal(SIGINT) occurred." << std::endl;
// do something like writing data to a file
first = false;
}
else {
std::cout << " A signal(SIGINT) occurred, exiting...." << std::endl;
exit(0);
}
}
}
int main() {
// Construct a signal set registered for process termination.
boost::asio::io_service io;
boost::asio::signal_set signals(io, SIGINT);
// Start an asynchronous wait for one of the signals to occur.
signals.async_wait(handler);
io.run();
size_t i;
for(i=0;i<std::numeric_limits<size_t>::max();++i){
// time stepping loop, do some computations
}
std::cout << i << std::endl;
return 0;
}
When your first event is handled, you don't post any new work on the service object, so it exits.
This means that then (after the ioservice exited) the tight loop is started. This may not be what you expected.
If you want to listen for SIGINT again, you have to wait for the signal set again from the handler:
#include <boost/asio.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/bind.hpp>
#include <boost/atomic.hpp>
#include <iostream>
void handler(boost::asio::signal_set& this_, boost::system::error_code error, int signal_number) {
if (!error) {
static boost::atomic_bool first(true);
if(first) {
// do something like writing data to a file
std::cout << " A signal(SIGINT) occurred." << std::endl;
first = false;
this_.async_wait(boost::bind(handler, boost::ref(this_), _1, _2));
}
else {
std::cout << " A second signal(SIGINT) occurred, exiting...." << std::endl;
exit(1);
}
}
}
int main() {
// Construct a signal set registered for process termination.
boost::asio::io_service io;
boost::asio::signal_set signals(io, SIGINT);
// Start an asynchronous wait for one of the signals to occur.
signals.async_wait(boost::bind(handler, boost::ref(signals), _1, _2));
io.run();
return 2;
}
As you can see I bound the signal_set& reference to the handler in order to be able to async_wait on it after receiving the first signal. Also, as a matter of principle, I made first an atomic (although that's not necessary until you run the io_service on multiple threads).
Did you actually wish to run the io_service in the background? In that case, make it look like so:
signals.async_wait(boost::bind(handler, boost::ref(signals), _1, _2));
boost::thread(boost::bind(&boost::asio::io_service::run, boost::ref(io))).detach();
while (true)
{
std::cout << "Some work on the main thread...\n";
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
With typical output:
Some work on the main thread...
Some work on the main thread...
Some work on the main thread...
^CSome work on the main thread...
A signal(SIGINT) occurred.
Some work on the main thread...
Some work on the main thread...
^CSome work on the main thread...
A second signal(SIGINT) occurred, exiting....

Random error in code

I have a function which has to search all pcs in the network and look for responses:
DLL void get_remote_ip(void)
{
initWSA();
if(create_Sockets() == INVALID_SOCKET)
{
std::cerr << "Socket Error\n";
return;
};
initiate_TXRX_variables();
boost::asio::io_service io_service;
udp_server_search server(io_service);
std::cout << "No crash till here\n";
boost::thread thread_1 = boost::thread(ultra_spam_network_udp);
boost::asio::deadline_timer dt1 = boost::asio::deadline_timer(io_service);
boost::thread thread_2(boost::bind(&boost::asio::io_service::run, &io_service));
dt1.expires_from_now(boost::posix_time::milliseconds(2000));
dt1.wait();
//ip_adr_ccd = server.return_ip(0);
if(ip_adr_ccd != "localhost" && ip_adr_daisy != "localhost")
{
std::cout << "Remote IP of CCD is: " << ip_adr_ccd << '\n';//For debug
std::cout << "Remote IP of TERS is: " << ip_adr_daisy << '\n'; //For debug
}
else
std::cout << "No new remote ips found\n";
//std::cout << Use << '\n';
//thread_1.join();
}
When I call this function, my program crashes sometimes without telling me why, it just tells me "Exception error in <hex-address>". Where is my bug? Is it possible that one thread tries to join, but the other one has not finished now (which can be possible because the errors are quite random and are killing the std::cout-output of the main thread within writing)?
Thank you!
I found my mistake, I have to stop io_service first and then call thread_2.join(), otherwise my thread_2 is crashing.
You don't seem to stop the io_service in a clean way. io_serice::run blocks while there are ramining handlers to be dispatched. My guess is that your udp_server_search causes an endless queueing of handlers. So either your join never finishes because it has to wait for the run() to return which never happens, or if you comment it out, leaving get_remote_ip will destroy the io_service while in thread_2 the run method continues to be executed on a now destroyed object.
What could solve your problem (besides from breaking the endless queue on the server) is manually stopping the ioservice:
boost::thread thread_2( [&]{io_service.run();} );
//do stuff, wait for the timer etc...
io_service.stop(); //run should return as soon as possible
thread_2.join(); //clean finishing of the service.

How to deal with shared data when throwing exceptions

When having multiple threads using shared data, how does one correctly handle the destruction of that data when exceptions are thrown?
I'm working on an application where I want one process to be doing work while waiting for a result sent from another process over a network. I implemented a class that creates a thread to wait for the result, something like the following (actual code is too large to post here, so this is a small example):
class Notifier {
public:
Notifier(Client* _client) : value(-1), client(_client) {
listener = boost::thread(&Notifer::Listen, this);
}
void Listen() {
try {
int rec = client->Receive(); //blocking call to receive data over a socket
boost::scoped_lock sl(mutex);
value = rec;
} catch (...) {
cout << "Exception thrown in listener" << endl;
}
}
int Get() {
boost::mutex::scoped_lock sl(mutex);
return value;
}
private:
int value;
boost::mutex;
boost::thread listener;
Client* client;
}
int main() {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
}
}
This works fine for me until I add exception handling:
int main() {
try {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
throw exception();
}
} catch(...) {
cout << "Exception thrown in main" << endl;
}
return 0;
}
I get the error
"boost: mutex lock failed in pthread_mutex_lock: Invalid argument".
My guess is that, when the exception gets thrown, the stack for the main function gets unwound, destroying the mutex. Then the Receive() call in the Listen function returns and the scoped_lock constructor tries to lock the mutex, which doesn't exist, resulting in the error.
Can someone confirm that this is indeed what is happening? If so, is there a way to communicate to the thread that that the mutex no longer exists or that the thread should terminate? Or is there a more exception-safe way of doing what I'm trying to do?
You have to write a correct destructor for Notifier class, which would cancel all blocked calls (i.e. unblock client->Receive()) and then terminate listener thread. Also you need to modify Notifier::Listen() to periodically check for thread termination request... then everything will be Ok.