segmentation fault using boost asio in linux.

Hi, I am using Boost Asio and hitting a segmentation fault crash in ubuntu. I don't have any issue when this is run in the windows. it runs and after half an hour, it hits this crash. Below is the code that starts from beginning to the place that the segmentation fault happened. The interesting part is that I use io_strand all over the code and I don't see any thread-safety issue. In the program I use 2 threads that run the worker io_servece.run(). I also put some printf in the HandleSend() just before the crash. i can see that itr pointer is not valid even though m_pending_sends has one element in the list that is supposed to be this itr pointer. What could be wrong here? Thanks a lot, mustafa 06:49.20 [dbg] void Connection::HandleSend() itr size: 2869978912 m_pending_sends.size(): 1 void Connection::Start() { m_stopped = false; m_start_time = boost::posix_time::second_clock::local_time(); boost::system::error_code ec; boost::asio::ip::tcp::resolver resolver( m_hive->GetService() ); boost::asio::ip::tcp::resolver::query query( m_host, boost::lexical_cast< std::string >( m_port ) ); boost::asio::ip::tcp::resolver::iterator endpointIterator = resolver.resolve( query ); Connect(endpointIterator); return; } void Connection::Connect(tcp::resolver::iterator endpoint_iter) { LDBG_ << "void Connection::Connect()-1 symbol: " << m_symbol; if (endpoint_iter != boost::asio::ip::tcp::resolver::iterator()) { boost::asio::ip::tcp::endpoint endpoint = *endpoint_iter; m_socket.async_connect( endpoint, m_io_strand.wrap( boost::bind( &Connection::HandleConnect, shared_from_this(), boost::asio::placeholders::error, endpoint_iter ) ) ); } else { Stop(); } return; } void Connection::HandleConnect( const boost::system::error_code & error, boost::asio::ip::tcp::resolver::iterator endpoint_iterator ) { LDBG_ << "void Connection::HandleConnect()-1 symbol: " << m_symbol << " error: " << error << " HasError " << HasError() << " m_hive->HasStopped() " << m_hive->HasStopped(); if ( error || HasError() || m_hive->HasStopped() ) { StartError( error ); } else { if ( m_socket.is_open() ) { OnConnect( m_path ); } else { Connect(++endpoint_iterator); } } return; } void MyConnection::OnConnect( const std::string & host, uint16_t port, const std::string & path ) { Recv(); Send(); } void Connection::Send() { if (m_stopped) return; std::string str = "GET " + m_path + " HTTP/1.0\r\n\r\n"; str += "Host: " + m_host + "\r\n"; str += "Accept: */*\r\n"; str += "Connection: keep-alive \r\n\r\n"; std::vector< uint8_t > request; std::copy( str.begin(), str.end(), std::back_inserter( request ) ); m_io_strand.post( boost::bind( &Connection::DispatchSend, shared_from_this(), request ) ); // start the heartbeat timer for the next send msg. StartTimerHeartbeat(); return; } void Connection::DispatchSend( std::vector< uint8_t > buffer ) { bool should_start_send = m_pending_sends.empty(); m_pending_sends.push_back( buffer ); if ( should_start_send ) { StartSend(); } return; } void Connection::HandleSend( const boost::system::error_code & error, std::list< std::vector< uint8_t > >::iterator itr ) { if ( error || HasError() || m_hive->HasStopped() ) { StartError( error ); } else { OnSend( *itr ); if ( !m_pending_sends.empty() ) { m_pending_sends.erase( itr ); <<<<<<<<====== Segmentation Fault happens here StartSend(); } } return; } void Connection::StartSend() { if ( !m_pending_sends.empty() ) { boost::asio::async_write( m_socket, boost::asio::buffer( m_pending_sends.front() ), m_io_strand.wrap( boost::bind( &Connection::HandleSend, shared_from_this(), boost::asio::placeholders::error, m_pending_sends.begin() ) ) ); } return; } -- View this message in context: http://boost.2283326.n4.nabble.com/segmentation-fault-using-boost-asio-in-li... Sent from the Boost - Users mailing list archive at Nabble.com.

I am using Boost Asio and hitting a segmentation fault crash in ubuntu. I don't have any issue when this is run in the windows. it runs and after half an hour, it hits this crash. Below is the code that starts from beginning to the place that the segmentation fault happened.
The interesting part is that I use io_strand all over the code and I don't see any thread-safety issue. In the program I use 2 threads that run the worker io_servece.run().
I also put some printf in the HandleSend() just before the crash. i can see that itr pointer is not valid even though m_pending_sends has one element in the list that is supposed to be this itr pointer.
What could be wrong here?
Is it possible that m_pending_sends changes between StartSend and HandleSend?

Hi Igor, I see what you are saying. let's say DispatchSend is called between StartSend and HandleSend. However, we do push_back a new element to the list in DispatchSend(). Adding a new element is still a problem? you think i should mutex these push_back and erase operations? I though io_strand handles all these issues. Thanks, mustafa -- View this message in context: http://boost.2283326.n4.nabble.com/segmentation-fault-using-boost-asio-in-li... Sent from the Boost - Users mailing list archive at Nabble.com.

I see what you are saying. let's say DispatchSend is called between StartSend and HandleSend. However, we do push_back a new element to the list in DispatchSend(). Adding a new element is still a problem?
It depends on the type of m_pending_sends - if it's std::vector, its iterators are invalidated on push_back.
you think i should mutex these push_back and erase operations? I though io_strand handles all these issues.
strand only guaratees that handlers won't be invoked concurrently: http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/io_servic...

m_pending_sends is std::list< std::vector< uint8_t > > m_pending_sends; since strand guarantees serialization, during DispatchSend, the push_back will be called and let's say this invalidates the pointers. Then when HandleSend is called, the pointers are supposed to be fine, isn't it? Thanks, mustafa -- View this message in context: http://boost.2283326.n4.nabble.com/segmentation-fault-using-boost-asio-in-li... Sent from the Boost - Users mailing list archive at Nabble.com.

I have one more question. If i use one thread instead of 2 threads utilizing io_service.run(), I wouldn't see this issue, right? since only one CallBack is handled by the same thread in sequential way. Thanks, mustafa -- View this message in context: http://boost.2283326.n4.nabble.com/segmentation-fault-using-boost-asio-in-li... Sent from the Boost - Users mailing list archive at Nabble.com.

I have one more question. If i use one thread instead of 2 threads utilizing io_service.run(), I wouldn't see this issue, right? since only one CallBack is handled by the same thread in sequential way.
Thanks, Mustafa
Hi Mustafa, You're probably seeing the segfault because the buffer you passed to async_send is invalidated before the send completes (due to vector reallocation). So you need to ensure that the buffer remains valid until the async_send completion is invoked, for instance your container could be managed by a shared_ptr that is passed to the completion handler. Best regards, Martin Dyring-Andersen

implementing shared_ptr instead of iterator during boost::asio::async_write() call fixed the issue. I don't see segmentation fault anymore. Thanks a lot, mustafa -- View this message in context: http://boost.2283326.n4.nabble.com/segmentation-fault-using-boost-asio-in-li... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (3)
-
Igor R
-
Martin Dyring-Andersen
-
mozdemir