boost asio - SSL async_read and async_write from one thread
Asked Answered
L

4

6

I know that OpenSSL, boost asio SSL implementation is based on, doesn't allow concurrent SSL_read() and SSL_write() (i.e. SSL_read() and SSL_write() executed by different threads).

Is it safe to call boost asio async_read() and async_write() on SSL socket from the same thread?

Thanks

Licorice answered 23/8, 2013 at 18:28 Comment(0)
S
4

The requirement for boost::asio::ssl:::stream is for thread safety; it does not place a requirement as to which thread may initiate operations:

Distinct objects: Safe.

Shared objects: Unsafe. The application must also ensure that all asynchronous operations are performed within the same implicit or explicit strand.

If the application only has one thread processing the io_service, and async_read() and async_write() are initiated from within that thread, then it is safe, as the operation and completion handler(s) are running within an implicit strand.

On the other hand, if multiple threads are processing the io_service, then an explicit strand is necessary. The async_read() and async_write() operations need to be initiated from within a strand, and the completion handlers need to be wrapped by the same strand.

For more details on Boost.Asio's thread safety requirements, strands, and composed operations, consider reading this answer.

Sholom answered 23/8, 2013 at 22:25 Comment(0)
S
3

It is safe to call async_read() and async_write() on SSL socket from the same thread, but in general case it is not enough to avoid concurrency issues with ssl::stream. The actual requirement is provided in ssl::stream documentation:

Thread Safety (...) Shared objects: Unsafe. The application must also ensure that all asynchronous operations are performed within the same implicit or explicit strand.

Of course, the standard boost::asio requirement to ensure that:

  • no other read operations are performed until async_read handler gets called, and
  • no other write operations are performed until async_write handler gets called.

must also be met.

Note, that it is allowed to schedule a read operation while a write operation is underway and conversely. Simultaneous asynchronous read and write operations are possible in ssl::stream thanks to handling OpenSSL's network needs asynchronously through BIO mechanism. SSL_read() and SSL_write() manifest their needs to communicate by returning SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE error codes. These error codes are used by ssl::stream implementation to schedule the network operations asynchronously. A read or write operation on ssl::stream may need multiple both read and write operations on the underlying network socket and multiple calls to SSL_read() / SSL_write(), which will be performed from asynchronous network operation completion handlers (particularly not from the original async_read/async_write call), this is why it is not enough to ensure that async_read and async_write are not called simultaneously, but a strand is needed.

Strychnic answered 23/8, 2013 at 20:47 Comment(0)
P
1

It is safe. But simulateous 2 or more async_write-s on same socket are unsafe and will segfault often(at least for SSL case).

Petropavlovsk answered 23/8, 2013 at 20:24 Comment(1)
It won't segfault, it will interleave data.Schoolbook
L
0

A way of doing this is to construct the ssl::stream using a strand as it's execution context. You can then perform async_read and async_write operations from that strand. Both of these operations can be scheduled at the same time.

You just have to make sure that the context the stream was constructed with and the context that async_read and async_write are called from are effectively an explicit or implicit strand.

Related question: boost asio ssl async_read + async_write within a strand is failing

Limn answered 25/10, 2022 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.