asio: async ops in multithreading environment

Hi! I have strange crashes of my application that uses async ops in multiple threads. Before I describe my vision of the problem I point the following: 1) I'm aware that shared access to the same socket from multiple threads is unsafe. 2) All operations which my code issues on the same socket are made under mutex. As far as I understand, the following happens: 1) One thread issues scatter-gather boost::asio::async_write() for boost::array<boost::asio::const_buffer, 2> on socket A. 2) Another thread closes socket A after that. 3) Meantime (simultaneously with 2), first buffer write is completed and one of the threads running io_service::run() starts to execute second part of async_write from 1). In this place application segfaults: #0 0x00007fa3a3a2c4eb in boost::asio::detail::epoll_reactor::start_op (this=0x19c3410, op_type=1, descriptor=27, descriptor_data=@0x7f9dfc013260, op=0x7f9dfc2d2130, allow_speculative=true) at boost-1_51/boost/asio/detail/impl/epoll_reactor.ipp:219 #1 0x00007fa3a3a2bf63 in boost::asio::detail::reactive_socket_service_base::start_op (this=0x19c4338, impl=..., op_type=1, op=0x7f9dfc2d2130, is_non_blocking=true, noop=false) at boost-1_51/boost/asio/detail/impl/reactive_socket_service_base.ipp:211 #2 0x00007fa3a3af4ec5 in boost::asio::detail::reactive_socket_service_base::async_send (this=0x19c4338, impl=..., buffers=..., flags=0, handler=...) at boost-1_51/boost/asio/detail/reactive_socket_service_base.hpp:212 #3 0x00007fa3a3af90bf in boost::asio::stream_socket_service<boost::asio::ip::tcp>::async_send (this=0x19c4310, impl=..., buffers=..., flags=0, handler=...) at boost-1_51/boost/asio/stream_socket_service.hpp:298 #4 0x00007fa3a3b05992 in boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp>
::async_write_some (this=0x7f9dfc013250, buffers=..., handler=...) at boost-1_51/boost/asio/basic_stream_socket.hpp:676
because descriptor_data equals null-pointer here. The problem is: second write which is issued internally by boost cannot be protected by the same mutex which is used for protected access to the socket in my code. So, the question is: how can I safely close the socket? -- Max

The problem is: second write which is issued internally by boost cannot be protected by the same mutex which is used for protected access to the socket in my code.
So, the question is: how can I safely close the socket?
You should use strands: http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/overview/core/stran...

Hi Igor! What do you mean by "use strands". I'm using strands for my completion handlers. Also I can use strand to commit async operations and to post close(). But that fact doesn't help given that the second buffer write (from my scenario) is not initiated from within the same strand. It seems that some internal boost strand is used to commit second and later buffer writes when using scatter-gather async_write API. So the question "how to safely close socket?" still remains. 2013/3/6 Igor R <boost.lists@gmail.com>:
The problem is: second write which is issued internally by boost cannot be protected by the same mutex which is used for protected access to the socket in my code.
So, the question is: how can I safely close the socket?
You should use strands: http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/overview/core/stran... _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

The problem is: second write which is issued internally by boost cannot be protected by the same mutex which is used for protected access to the socket in my code.
So, the question is: how can I safely close the socket?
You should use strands: http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/overview/core/stran...
What do you mean by "use strands". I'm using strands for my completion handlers. Also I can use strand to commit async operations and to post close(). But that fact doesn't help given that the second buffer write (from my scenario) is not initiated from within the same strand. It seems that some internal boost strand is used to commit second and later buffer writes when using scatter-gather async_write API. So the question "how to safely close socket?" still remains.
All the internal/intermediate completion handlers of the composed operation async_write would use the same strand, as stated in the docs (see the link in my previous comment): "In the case of composed asynchronous operations, such as async_read() or async_read_until(), if a completion handler goes through a strand, then all intermediate handlers should also go through the same strand. This is needed to ensure thread safe access for any objects that are shared between the caller and the composed operation (in the case of async_read() it's the socket, which the caller can close() to cancel the operation)." So if you post close() to *this* strand - it won't cause race-condition with the composed operation in your scenario, will it?
participants (2)
-
Igor R
-
Max Dmitrichenko