简体   繁体   中英

Segmentation fault with boost::asio, asynchronous udp-server with deadline_timer

I am having trouble with a server program using the boost::asio library.

The Server class is very much like the one presented in the boost asio tutorial "asynchronous udp-server"

The class has a public method ("sendMessageTo"), which is called by a message - processor object, here the segmentation fault occurs, if the method is invoked by the deadline_timer thread. It occurs with the call of new std::string(msg, len), this is puzzeling me. msg contains what it should contain, and len too.

void Server::sendMessageTo(const char* msg, size_t len, udp::endpoint to)
{
    boost::shared_ptr<std::string> message( new std::string (msg,len) );
    socket.async_send_to(boost::asio::buffer(*message), to,
                         boost::bind(&Server::handleSend, this, message,
                                     boost::asio::placeholders::error,
                                     boost::asio::placeholders::bytes_transferred));
}

When the method "sendMessageTo" is called on the first attempt, everything works fine: It is called later in the same thread, that is opened by the "handleReceive" method of the server class.

My message-processor object is some kind of state-machine, that keeps the remote-endpoint, and in some states periodically wants to send some udp Messages back to the endpoint. Therefor a asio::deadline_timer is used. The deadline timer is created with the same io_service, the udp-server runs on. When the timer is revoked for the first time, the state_handling method inside the message_processor object calls the "sendMessageTo" method an segmentation fault occurs. All arguments of "sendMessageTo" are valid and contain the expected values.

The constructor head of my message-processor class (called Transaction)

Transaction::Transaction(ClientReference *cli, ServerReference *serv)
    : timer(*(serv->getIOService()), boost::posix_time::milliseconds(TRANSACTION_THREAD_SLEEP_MILLISEC)),
      clientEndpoint(serv->getEndpoint())

timer is the asio::deadline_timer object, and clientEndpoint is the udp::endpoint

the server response is sent inside the method Transaction::runThread()

server->sendMessageTo(&encryptedMsgBuf[0], size, clientEndpoint);

encryptedMsgBuf is a char array buffer, that stores the encrypted message, and it is part of the Transaction - object.

at the end of the method Transaction::runThread() the deadline_timer is called onto the method runThread() to reactivate it until the final state is reached:

if (state != done && state != expired) 
    timer.async_wait(boost::bind(&Transaction::runThread, this));

Thank you in advantage.

I'm not 100% sure on this one, since I can't locally reproduce your error from what you've posted, but I strongly suspect your problem is due to the scoping of the message string variable. I have had some issues with boost::shared_ptr in the past, where the shared_ptr has been destructed earlier than expected. If this is the case, then shared_ptr message may be getting destructed at the end of the call to Server::sendMessageTo() , and when the asynchronous tranmission actually attempts to start, that memory has been deallocated causing a segfault.

In general, I like to keep the buffers which I am actually transmitting from and receiving to as private members of my server and client classes to ensure they are statically scoped and won't vanish on me unexpectedly half-way through a transmit or receive. It can cost a bit in memory footprint, but I find it gives me a lot of peace-of-mind. If this approach doesn't give you any joy, let me know and I'll see if I can reproduce the error locally. (At the moment my 'local reproduction' attempts have consisted of me hacking an old "server-client using ASIO" example to allocate the TX buffer as you've indicated above, then thrash some memory so if the TX is trying to do further heap access it should segfault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM