async_read()
は、バッファがいっぱいになるかエラーが発生するまで読み取ります。これらの条件のいずれも満たさずに読み取りハンドラが呼び出されている場合、未定義のビヘイビアが呼び出されている可能性があります。
異なるオブジェクト:安全なこの特定のケースでは、コードがboost::asio::ssl:::stream
のためのスレッドの安全性の要件に違反します。
共有オブジェクト:安全ではありません。また、アプリケーションは、すべての非同期操作が同じ暗黙のストランド内で実行されることを保証する必要があります。
具体的には、書き込み操作は明示的なストランド(connection::strand_
)内で実行されます。しかし、読み出し動作はストランドの外部で行われる。サーバを実行する複数のスレッドが存在するため、プログラムはすべての操作が同じストランド内で実行されることを保証できません。 connection::strand_
ストランド内からasync_read
操作を実行する明示的に、この問題を解決するには
void connection::async_write(...)
{
...
// `strand_` protects `message_queue_` and guarantees that writes to
// `socket_` are only occurring within the strand.
strand_.post([...]()
{
auto empty = message_queue_.empty();
message_queue_.push([=]()
{
...
// Intermediate and final handlers are 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 are performed within `strand_`.
[](...)
{
boost::asio::async_read(socket_, ...);
}
});
}
。さらに、操作のためのリード・ハンドラは、同様にconnection::strand_
内にラップする必要があります。
void connection::async_read(...)
{
strand_.post([...](...)
{
// async_read is now performed with the strand.
boost::asio::async_read(socket_, ...,
// Intermediate and final handlers are performed within the strand.
strand_.wrap([](...)
{
boost::asio::async_read(socket_, ...);
});
});
}
鎖内で行われるすべての非同期操作とハンドラは、this答えを見ることを保証する方法の詳細については。
[mcve]を提供してください。 (例えば、 'inbound_header_.size()'が '0'、' socket_'に対するスレッドセーフティ要件を満たさない、API契約に違反する下位レベルのドライバなど)が複数ある可能性があります。 –
は開始ポストに1を加えました – ACB
[mcve]は、最小限にして、しばしばゼロから作成し、元の質問に含まれている必要があります。外部リンク、およびそれらに含まれる可能性のある重要な情報は、腐敗する可能性があります。 –