【发布时间】:2016-01-07 14:25:46
【问题描述】:
TLDR:Strands 序列化跨完成处理程序共享的资源:这如何防止 ssl::stream 实现并发访问 SSL 上下文(内部使用)以进行并发读/写请求(stream::ssl 不是全双工) ?请记住,strand 仅序列化完成处理程序调用或读/写请求的原始队列。 [感谢 sehe 帮助我更好地表达这一点]
我花了一天的大部分时间阅读有关 ASIO、SSL 和 strands 的信息;主要是在 stackoverflow(其中有一些非常详细且表达良好的解释,例如Why do I need strand per connection when using boost::asio?)和 Boost 文档;但有一点还不清楚。
显然,strand 可以在同一 strand 中序列化调用回调,因此也可以序列化对这些 strand 共享资源的访问。
但在我看来 boost::asio::ssl::stream 的问题不在于完成处理程序回调,因为它不是在 SSL 上下文上同时运行的回调,而是 ssl::stream就是实现。
我不能确定在调用 async_read_some 和 async_write_some 时使用 strands,或者在完成处理程序中使用 strands 会阻止 io 引擎在不同线程中同时在 SSL 上下文上运行。
在调用 async_read_some 或 async_write_some 时显然使用 strand 将意味着读取和写入不能在同一时刻排队,但我不明白这如何阻止内部实现同时执行读取和写入操作如果封装的 tcp::socket 同时准备好读写,则在不同线程上的时间。
在这个问题boost asio - SSL async_read and async_write from one thread 的最后一个答案末尾的评论声称并发写入 ssl::stream 可能会出现段错误,而不仅仅是交错,这表明实现没有采用必要的锁来防止并发访问。
除非实际延迟的套接字写入绑定到排队的线程/链(我看不出这是真的,否则会破坏工作线程的有用性),我怎么能确信它是可能的在同一个 ssl::stream 上排队读取和写入,或者这种方式可能是什么?
也许 async_write_some 立即使用 SSL 上下文处理所有数据,以生成加密数据,然后变成普通套接字写入,因此不能与同一链上的读取完成处理程序冲突,但它不会'这并不意味着在完成处理程序在链上排队之前它不能与内部实现套接字读取和解密冲突。不要介意可能发生的透明 SSL 会话重新协商......
我注意到:Why do I need strand per connection when using boost::asio?“组合操作的独特之处在于,对流的中间调用是在处理程序的链中调用的,如果存在的话,而不是启动组合操作的链。”但我不确定我指的是“对流的中间调用”。这是否意味着:“该流实现中的任何后续处理”?我怀疑不是
最后,为什么 - 哦 - 为什么,为什么 ssl::stream 实现不使用 futex 或其他在没有冲突时便宜的锁?如果遵循链规则(隐式或显式),则成本几乎不存在,但否则会提供安全性。我之所以问,是因为我刚刚将 Sutter、Stroustrup 和其他人的宣传转变为 ssl::stream,它似乎很容易遵循某些咒语,但几乎不可能知道你的代码是否真的安全.
【问题讨论】:
标签: c++ multithreading ssl boost