boost asio - C++ thread does not join even after long waiting -


i trying test boost asio socket listener using boost unit test. purpose of listener listening on port , read ever comes in , save queue , send http response header.

as first step, have created client send messages listener , read response message comes listener. have created thread start listener. main thread send , receive messages , listener. able send , receive messages between client , listner. when try join not join , keeps on waiting join(i guess).

please me went wrong.

thanks in advance.

listener.hpp

#ifndef listener_hpp #define listener_hpp #include <iostream> #include <stdio.h> #include <atomic> #include <boost/asio.hpp> #include "sharedqueue.hpp"  using namespace std; using namespace boost; using boost::asio::ip::tcp;  class listener{  private: int port; std::atomic<bool> m_stop; boost::system::error_code error; boost::asio::io_service io_service; std::shared_ptr<sharedqueue> queue_ptr; void savemessagetoqueue(std::string,std::string); listener(int porttolisten, std::shared_ptr<sharedqueue>  queue_unique_ptr); listener(const listener&); listener& operator=(const listener&); public: static listener& getinstance(int porttolistenon,         std::shared_ptr<sharedqueue>   queue_unique_ptr); void listen(); }; #endif /* listener_hpp */ 

listener.cpp

 #include "listener.hpp"  listener::listener(int porttolisten, std::shared_ptr<sharedqueue>   queue_unique_ptr):port(porttolisten), queue_ptr(queue_unique_ptr),m_stop(false)  {;}  listener& listener::getinstance(int porttolistenon, std::shared_ptr<sharedqueue>   queue_unique_ptr)  {   static listener instance(porttolistenon,  queue_unique_ptr);   return instance;  }  void listener::stoplisten(){  m_stop = true;  }  void listener::listen()  {   try{     tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port));     while(!m_stop)     {         std::cout<<"server listening on port "<<port<<std::endl;         boost::asio::ip::tcp::socket socket(io_service);         acceptor.accept(socket);         std::cout<<"connection request accepted "<<std::endl;         std::array<char, 512> buf;         socket.read_some(boost::asio::buffer(buf), error);         std::string responseback =" http:300";         boost::asio::write(socket, boost::asio::buffer(responseback, responseback.size()), error);     }   }   catch (std::exception& e)   {     std::cerr <<"listener exception : "<< e.what() << std::endl;     exit(0);   }   } 

sharedqueue.hpp

  #ifndef sharedqueue_hpp   #define sharedqueue_hpp   #include <stdio.h>   #include <iostream>   class sharedqueue{   public:   sharedqueue(){};   void pushtoqueue(std::string str){};   };   #endif /* sharedqueue_hpp */ 

clienttesthelper.hpp

  #ifndef clienttesthelper_hpp   #define clienttesthelper_hpp    #include <iostream>   #include <boost/asio.hpp>   using namespace std;   class clienttesthelper   {     string address = "";     public:     clienttesthelper(std::string addresstopush){     this->address = addresstopush;    };   ~clienttesthelper(){};   std::string sendmessage(string message);   };    #endif /* clienttesthelper_hpp */ 

clienttesthelper.cpp

#include "clienttesthelper.hpp" std::string clienttesthelper::sendmessage(string message){ boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(address, boost::asio::ip::resolver_query_base::numeric_service); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); boost::asio::ip::tcp::socket socket(io_service); boost::asio::connect(socket, endpoint_iterator); boost::asio::streambuf writebuffer; boost::asio::streambuf readbuffer; std::string str = message; boost::system::error_code error; boost::asio::write(socket, boost::asio::buffer(str, str.size()), error); std::array<char,1024> buf; socket.read_some(boost::asio::buffer(buf), error); std::string respo = buf.data(); cout<<respo<<std::endl; return respo; } 

listenertest.hpp

#ifndef listenertest_hpp #define listenertest_hpp  #define boost_test_dyn_link #define boost_test_main  #include <iostream> #include <stdio.h> #include <thread> #include <boost/test/unit_test.hpp> #include "listener.hpp" #include "clienttesthelper.hpp" #include "sharedqueue.hpp"  struct listenertestfixture{ public: void startlisten(listener &receiver){     receiver.listen(); } std::shared_ptr<sharedqueue> myqueue  = std::make_shared<sharedqueue>(); listener &receiver = listener::getinstance(8282, myqueue); void dorun(){     receiver.listen(); } clienttesthelper *client = new clienttesthelper("8282"); listenertestfixture(){}; ~listenertestfixture(){}; }; #endif /* listenertest_hpp */ 

listenertest.cpp

#include "listenertest.hpp"  boost_fixture_test_case(connectiontest, listenertestfixture) { std::thread t1(&listenertestfixture::dorun, *this); std::string response = ""; response   = client->sendmessage("somerandom messages \r\n\r\n\r\n"); //receiver.~listener(); receiver.stoplisten(); std::cout<<"response received "<<response; t1.join(); std::cout<<"finished testing "<<endl; } 

console output clarification:

running 1 test case... server listening on port 8585 connection request accepted  server listening on port 8585   http:300 

after execution did not stopped instead waiting join.

edit: modified listener class added member m_stop , stoplisten(), changed for(;;) while(!m_stop). header file included.

receiver.~listener(); doesn't think does. line of code can't work , has come out.

what cause destructors called on members of receiver. won't (directly) interrupt call listen(). outcome thread executing listen() perform undefined behaviour , means fail end in way notifies join().

in short main thread wait forever because you've "pulled rug out" under receiver().

even if somehow worked compiler have added implicit call of receiver.~listener() @ end of main() , crash there if chance makes far.

the normal solution add member listener such std::atomic<bool> m_stop; (or if prefer boost equivalents if you're using boost) initialise false in constructor (not listen()) , call member called stop() sets true before calling join().

you replace non-terminating loop in listen() while(!stop).

that way main thread can notify listening come orderly conclusion @ end of loop.

there no general way of making thread "just" or "suddenly" stop cleanly. can't anticipate point @ in process or resources using. might in library call , corrupt heap, operating system, file system, anything.

as aside java has thread method called stop() pretty deprecated after added. there no safe way implement or use it.


it rare should ever call destructor directly. use case know you've used placement new , don't want return space heap. it's rarer in modern c because things recycling space in containers handed on std containers std::vector<>.

most implementations of std::vector<> call destructors because if resize vector down needs destruct object not reallocate internal storage.

you should pretty never call destructor on statically allocated object.


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -