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.
Related
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
I was learning boost asio documentation.I came across this deadline_timer example.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
/*This timer example shows a timer that fires once every second.*/
void print(const boost::system::error_code& e, boost::asio::deadline_timer* t, int* count)
{
if (*count < 5)
{
std::cout << *count << std::endl;
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
t->async_wait(boost::bind(print,boost::asio::placeholders::error, t, count));
}
}
int main()
{
boost::asio::io_service io;
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(10));
auto myfunc = boost::bind(print, boost::asio::placeholders::error, &t ,&count);
t.async_wait(myfunc);
std::cout << "async wait " << std::endl;
io.run();
std::cout << "Just called io.run() " << std::endl;
std::cout << "Final count is " << count << std::endl;
return 0;
}
The async_wait() function seems to be blocking (i.e waiting for the 10 second timer to expire)
The output from the above program is as follows.
async wait
0
1
2
3
4
Just called io.run()
Final count is 5
I would expect an async_wait() to create a separate thread and wait for the timer to expire there meanwhile executing the main thread.
i.e I would expect the program to print
Just called io.run()
Final count is 5
while waiting for the timer to expire.? Is my understanding wrong?
This is my understanding of async_wait(). This implementation looks more like a blocking wait. Is my understanding wrong? What am I missing?
The io.run(); statement is the key to explaining the difference between the output you're getting and the output you're expecting.
In the ASIO framework, any asynchronous commands need to have a dedicated thread to run the callbacks upon. But because ASIO is relatively low-level, it expects you to provide the thread yourself.
As a result, what you're doing when you call io.run(); within the main thread is to specify to the framework that you intend to run all asynchronous commands on the main thread. That's acceptable, but that also means that the program will block on io.run();.
If you intend the commands to run on a separate thread, you'll have to write something like this:
std::thread run_thread([&]() {
io.run();
});
std::cout << "Just called io.run() " << std::endl;
std::cout << "Final count is " << count << std::endl;
run_thread.join();
return 0;
The async_wait function isn't blocking, run is. That's run's job. If you don't want a thread to block in the io_service's processing loop, don't have that thread call run.
The async_wait function doesn't create any threads. That would make it expensive and make it much harder to control the number of threads servicing the io_service.
Your expectation is unreasonable because returning from main terminates the process. So who or what would wait for the timer?
I use a 3rd-party-library (dcerpc) for my application being a rpc server.
Let's say the 3rd party function are in the namespace third.
I call third::listen in a thread, in order to listen for incoming requests.
"Third" provides all the mechanisms to interrupt this listen and properly exit the thread, but either it doesn't work, or I don't do it the correct way.
I first try everything with the library tools (demo sample, mail-list, browse the source code to understand...) but with no success.
So I try an alternative: violently kill the listening thread.
But third::listen has no cancellation point, I guess.
So this code (I simulate third::listen with listen function above):
void* listen(void*)
{
cout << "listening for calls...." << endl;
while (true) {}
printf ("Server stoppped listening\n");
return 0;
}
int main()
{
pthread_t thread = 0;
int res = pthread_create(&thread, 0, listen, 0);
cout << "pthread_create res: " << res << endl;
sleep(1);
bool isThreadRunning = (pthread_tryjoin_np(thread, 0) != 0);
cout << "Thread is running: " << isThreadRunning << endl;
res = pthread_cancel(thread);
cout << "pthread_cancel res: " << res << endl;
sleep(1);
isThreadRunning = (pthread_tryjoin_np(thread, 0) != 0);
cout << "Thread is running: " << isThreadRunning << endl;
res = pthread_join(thread, 0);
cout << "pthread_join res: " << res << endl;
return 0;
}
will output:
pthread_create res: 0
listening for calls....
Thread is running: 1
pthread_cancel res: 0
Thread is running: 1
and pthread_join(thread, 0) blocks (logic because no cancellation point).
My question: how to kill this thread !!
I tried with signals, but it stops my whole process, not only the thread.
My last try will be to isolate the listening in a dedicated fork process, but in my project context, it's really a pain to fork (that's another story).
Thanks a lot for any help.
Nicolas.
Whether a thread can be cancelled depends on its cancellation state and type. The default state is enabled. So that's fine. But the default type is deferred. That means when you send the thread a cancellation request, it's deferred until it reaches a cancellation point. Since your thread doesn't do anything in the empty loop, it doesn't reach a cancellation point at all. Hence, it doesn't respond to pthread_cancel().
You can set the cancellation type of the thread to PTHREAD_CANCEL_ASYNCHRONOUS which will typically make the thread exit. Call
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
before the loop.
Or you can call one of the functions that's a cancellation point. For example, do fflush(stdout); inside the loop.
POSIX list a number of functions as cancellation point. See cancellation points for such a list.
I can't make any comment on the "3rd party" library that doesn't respond to exiting threads with the limited information you have given.
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....
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.