Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost asio - SSL async_read and async_write from one thread

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

like image 530
dimba Avatar asked Aug 23 '13 18:08

dimba


3 Answers

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.

like image 196
Tanner Sansbury Avatar answered Nov 20 '22 11:11

Tanner Sansbury


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.

like image 39
Michał Wróbel Avatar answered Nov 20 '22 11:11

Michał Wróbel


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).

like image 20
PSIAlt Avatar answered Nov 20 '22 10:11

PSIAlt