c++ - boost async_read not reading all data with ssl -
im using boost asio networking , noticed when switched ssl networking code doesnt work anymore. problem seems line here:
boost::asio::async_read(socket_, boost::asio::buffer(inbound_header_), boost::bind(&connection::handle_read_header<handler>, this, boost::asio::placeholders::error, boost::make_tuple(handler)));
now far understand should read inbound_header_.size() bytes before calling handler. , works of time. read 0 bytes , still call handler error code 0. there im doing wrong? copied code boost asio serialization example thought should work.
minimal working sample here tested boost 1.61.0 on ubuntu 16.04 assert in connection::handle_read_header hit in first few seconds after launch every time.
async_read()
read until either buffers full or error occurs. if read handler being invoked neither of these conditions being satisfied, 1 potential culprit undefined behavior has been invoked. in particular case, code violates thread safety requirement boost::asio::ssl:::stream
:
distinct objects: safe.
shared objects: unsafe. application must ensure asynchronous operations performed within same implicit or explicit strand.
specifically, write operations performed within explicit strand (connection::strand_
); however, read operations performed outside of strand. there multiple threads running server, program fails ensure operations performed within same strand.
void connection::async_write(...) { ... // `strand_` protects `message_queue_` , guarantees writes // `socket_` occurring within strand. strand_.post([...]() { auto empty = message_queue_.empty(); message_queue_.push([=]() { ... // intermediate , final handlers performed within `strand_`. boost::asio::async_write(socket_, ... strand_.wrap([...](...) { ... message_queue_.front()() })); }); if (empty) message_queue_.front()(); }); } void connection::async_read(...) { // not performed within `strand_`, violating thread safety. boost::asio::async_read(socket_, ..., // neither intermediate, final handler, nor subsequent read // operations performed within `strand_`. [](...) { boost::asio::async_read(socket_, ...); } }); }
to resolve this, explicitly perform async_read
operations within connection::strand_
strand. furthermore, read handlers operations should wrapped within connection::strand_
well:
void connection::async_read(...) { strand_.post([...](...) { // async_read performed strand. boost::asio::async_read(socket_, ..., // intermediate , final handlers performed within strand. strand_.wrap([](...) { boost::asio::async_read(socket_, ...); }); }); }
for more details on how guarantee asynchronous operations , handlers performed within strand, see this answer.
Comments
Post a Comment