mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Fix race in writes during reads:
fix #261 This fixes a rare condition when responding to a ping or close frame where the wr_block_ stream variable is not correctly set for a short window of time.
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
1.0.0-b29
|
||||||
|
|
||||||
|
* Fix race in writes during WebSocket reads
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
1.0.0-b28
|
1.0.0-b28
|
||||||
|
|
||||||
* Split out and rename test stream classes
|
* Split out and rename test stream classes
|
||||||
|
@ -499,6 +499,8 @@ operator()(error_code ec,
|
|||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
case do_pong_resume:
|
case do_pong_resume:
|
||||||
|
BOOST_ASSERT(! d.ws.wr_block_);
|
||||||
|
d.ws.wr_block_ = &d;
|
||||||
d.state = do_pong_resume + 1;
|
d.state = do_pong_resume + 1;
|
||||||
d.ws.get_io_service().post(bind_handler(
|
d.ws.get_io_service().post(bind_handler(
|
||||||
std::move(*this), ec, bytes_transferred));
|
std::move(*this), ec, bytes_transferred));
|
||||||
@ -511,8 +513,7 @@ operator()(error_code ec,
|
|||||||
ec = boost::asio::error::operation_aborted;
|
ec = boost::asio::error::operation_aborted;
|
||||||
goto upcall;
|
goto upcall;
|
||||||
}
|
}
|
||||||
d.state = do_pong;
|
// [[fallthrough]]
|
||||||
break; // VFALCO fall through?
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
@ -520,14 +521,21 @@ operator()(error_code ec,
|
|||||||
if(d.ws.wr_close_)
|
if(d.ws.wr_close_)
|
||||||
{
|
{
|
||||||
// ignore ping when closing
|
// ignore ping when closing
|
||||||
|
if(d.ws.wr_block_)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(d.ws.wr_block_ == &d);
|
||||||
|
d.ws.wr_block_ = nullptr;
|
||||||
|
}
|
||||||
d.fb.reset();
|
d.fb.reset();
|
||||||
d.state = do_read_fh;
|
d.state = do_read_fh;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// send pong
|
// send pong
|
||||||
|
if(! d.ws.wr_block_)
|
||||||
|
d.ws.wr_block_ = &d;
|
||||||
|
else
|
||||||
|
BOOST_ASSERT(d.ws.wr_block_ == &d);
|
||||||
d.state = do_pong + 1;
|
d.state = do_pong + 1;
|
||||||
BOOST_ASSERT(! d.ws.wr_block_);
|
|
||||||
d.ws.wr_block_ = &d;
|
|
||||||
boost::asio::async_write(d.ws.stream_,
|
boost::asio::async_write(d.ws.stream_,
|
||||||
d.fb.data(), std::move(*this));
|
d.fb.data(), std::move(*this));
|
||||||
return;
|
return;
|
||||||
@ -541,18 +549,25 @@ operator()(error_code ec,
|
|||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
case do_close_resume:
|
case do_close_resume:
|
||||||
|
BOOST_ASSERT(! d.ws.wr_block_);
|
||||||
|
d.ws.wr_block_ = &d;
|
||||||
d.state = do_close_resume + 1;
|
d.state = do_close_resume + 1;
|
||||||
|
// The current context is safe but might not be
|
||||||
|
// the same as the one for this operation (since
|
||||||
|
// we are being called from a write operation).
|
||||||
|
// Call post to make sure we are invoked the same
|
||||||
|
// way as the final handler for this operation.
|
||||||
d.ws.get_io_service().post(bind_handler(
|
d.ws.get_io_service().post(bind_handler(
|
||||||
std::move(*this), ec, bytes_transferred));
|
std::move(*this), ec, bytes_transferred));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case do_close_resume + 1:
|
case do_close_resume + 1:
|
||||||
|
BOOST_ASSERT(d.ws.wr_block_ == &d);
|
||||||
if(d.ws.failed_)
|
if(d.ws.failed_)
|
||||||
{
|
{
|
||||||
// call handler
|
// call handler
|
||||||
d.state = do_call_handler;
|
|
||||||
ec = boost::asio::error::operation_aborted;
|
ec = boost::asio::error::operation_aborted;
|
||||||
break;
|
goto upcall;
|
||||||
}
|
}
|
||||||
if(d.ws.wr_close_)
|
if(d.ws.wr_close_)
|
||||||
{
|
{
|
||||||
@ -566,10 +581,12 @@ operator()(error_code ec,
|
|||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
case do_close:
|
case do_close:
|
||||||
|
if(! d.ws.wr_block_)
|
||||||
|
d.ws.wr_block_ = &d;
|
||||||
|
else
|
||||||
|
BOOST_ASSERT(d.ws.wr_block_ == &d);
|
||||||
d.state = do_teardown;
|
d.state = do_teardown;
|
||||||
d.ws.wr_close_ = true;
|
d.ws.wr_close_ = true;
|
||||||
BOOST_ASSERT(! d.ws.wr_block_);
|
|
||||||
d.ws.wr_block_ = &d;
|
|
||||||
boost::asio::async_write(d.ws.stream_,
|
boost::asio::async_write(d.ws.stream_,
|
||||||
d.fb.data(), std::move(*this));
|
d.fb.data(), std::move(*this));
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user