Reputation:
I got this code snippet in my application that i'm currently writing:
#include "ClientSession.hpp"
void ClientSession::start(void)
{
auto Self(shared_from_this());
//boost::asio::read(this->_Socket, boost::asio::buffer(this->_ReadBuffer));
//this->_Socket.get_io_service().post(boost::bind(&ClientSession::on_read, shared_from_this(), boost::system::error_code::error_code(), 0));
boost::asio::async_read(this->_Socket, boost::asio::buffer(this->_ReadBuffer), boost::bind(&ClientSession::on_read, Self, _1, _2));
}
void ClientSession::on_read(const boost::system::error_code& Err_, size_t Bytes_)
{
try
{
if(Err_)
{
if(!(Err_ == boost::asio::error::eof || Err_ == boost::asio::error::connection_aborted))
{
throw std::runtime_error(Err_.message());
}
return;
}
}
catch(std::exception& Ex_)
{
this->_OutputHandler.write_error(Ex_.what());
}
}
the code that calls ClientSession::start is:
void Application::start_accept()
{
using namespace boost::asio;
ip::tcp::endpoint Endpoint( ip::address::from_string(this->_Config.get_client_login_server().first), this->_Config.get_client_login_server().second );
this->_ClientAcceptor.open(Endpoint.protocol());
this->_ClientAcceptor.bind(Endpoint);
this->_ClientAcceptor.listen();
std::shared_ptr<ClientSession> Session = ClientSession::create_new(this->_AsioService, this->_OutputHandler);
this->_ClientAcceptor.async_accept(Session->get_socket(), boost::bind(&Application::handle_accept, shared_from_this(), Session, _1));
}
if i run the application with one of the commented out lines it works just fine (in the boost::asio::read version the transmitted message from the client got written in to the read buffer and during the post version the handler function gets called without any problems), but if try to use my application with the async_read part my whole application always crashes, without calling the complete handle or !even to read a byte!, at least it looks like that from the output that asio gives to me:
@asio|1373633560.834957|0*1|[email protected]_accept @asio|1373633573.324144|>1|ex=system:0 @asio|1373633573.324144|1*2|[email protected]_receive
I debbuged it to a file named "select_reactor.ipp" where the application tries to accquire an boost::asio::detail::mutex::scoped_lock and it looks like it is failing right there, the full code of the method is:
void select_reactor::start_op(int op_type, socket_type descriptor,
select_reactor::per_descriptor_data&, reactor_op* op,
bool is_continuation, bool)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
{
post_immediate_completion(op, is_continuation);
return;
}
bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
io_service_.work_started();
if (first)
interrupter_.interrupt();
}
I don't know maybe i'm doing something terribly wrong, but i don't know what, i hope someone can give me a hint what i can do to solve this error.
Based on the comments i got so far, i will add more complete code snippets: My io_service is inside my Application class:
class Application
: public std::enable_shared_from_this<Application>
{
typedef boost::asio::io_service Service;
typedef boost::asio::ip::tcp::acceptor Acceptor;
public:
Application(void)
: _ClientAcceptor(_AsioService), _ApplicationRunning(true)
{
}
~Application(void);
/*
* This is the main method which starts the actual program routine
* called in main()
*/
int run(void);
private:
/*
* Invokes the first accept and then invokes via async. handle_accept, which invokes itself repeatedly
*/
void start_accept(void);
/*
* handle_accept calls NewClient_->start to invoke the communication with this client
*/
void handle_accept(std::shared_ptr<ClientSession> NewClient_, const boost::system::error_code& Err_);
void loop_for_user_input(void);
bool handle_user_input(const std::string& Msg_);
/*
* This method invokes the threads that call io_service::run()
*/
static void start_service(Service& AsioService_) { try { AsioService_.run(); } catch(const std::exception& Ex_) { std::cout << Ex_.what() << std::endl; } }
private:
Configuration _Config;
Service _AsioService;
Acceptor _ClientAcceptor;
OutputHandler _OutputHandler;
bool _ApplicationRunning;
};
and the run method:
int Application::run(void)
{
try
{
this->_Config.load();
this->_OutputHandler.open(this->_Config.get_logs());
this->start_accept();
for(int i = 0; i < 4; i++)
{
std::thread t(start_service, std::ref(this->_AsioService));
t.detach();
}
this->loop_for_user_input();
}
catch(const std::runtime_error& Ex_)
{
this->_OutputHandler.write_error(Ex_.what());
}
return 0;
}
Upvotes: 0
Views: 323
Reputation:
I've found the error, it was just a typo in my _WIN32_WINNT preprocessor directive setting that to _WIN32_WINNT 0x0601 (for Windows 7) solved the problem.
Upvotes: 1