chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.85k stars 1.2k forks source link

A bug in io_context destruction with io_uring and coroutines #1235

Open martin-beran opened 1 year ago

martin-beran commented 1 year ago

An io_context destructor triggers Clang UB sanitizer in

#include <boost/asio.hpp>

namespace ba = boost::asio;

ba::awaitable<void> do_accept(ba::io_context& ctx, ba::ip::tcp::acceptor& acceptor)
{
    for (;;) {
        co_await acceptor.async_accept(ctx, ba::use_awaitable);
        ctx.stop();
    }
}

int main(int argc, char* argv[])
{
    ba::io_context ctx;
    ba::ip::tcp::acceptor acceptor(ctx, ba::ip::tcp::endpoint{ba::ip::tcp::v4(), 8080});
    ba::co_spawn(ctx, do_accept(ctx, acceptor), ba::detached);
    ctx.run();
    return 0;
}

If built by clang++-15 -std=c++20 -I ./boost_1_81_0 -o bug bug.cpp -fsanitize=undefined -D BOOST_ASIO_HAS_IO_URING -D BOOST_ASIO_DISABLE_EPOLL -g -luring, it reports:

$ UBSAN_OPTIONS=print_stacktrace=1 ./bug
boost_1_81_0/boost/asio/detail/io_object_impl.hpp:70:15: runtime error: member call on address 0x55d07ed29060 which does not point to an object of type 'boost::asio::detail::io_uring_socket_service<boost::asio::ip::tcp>'
0x55d07ed29060: note: object has invalid vptr
 00 00 00 00  29 ed 07 5d 05 00 00 00  cc 6e 55 ef 78 76 3b ee  00 00 00 00 00 00 00 00  30 97 2b 73
              ^~~~~~~~~~~~~~~~~~~~~~~
              invalid vptr
    #0 0x55d07dc4f37f in boost::asio::detail::io_object_impl<boost::asio::detail::io_uring_socket_service<boost::asio::ip::tcp>, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>::io_object_impl(boost::asio::detail::io_object_impl<boost::asio::detail::io_uring_socket_service<boost::asio::ip::tcp>, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>&&) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/io_object_impl.hpp:70:15
    #1 0x55d07dc4f194 in boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>::basic_socket(boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>&&) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/basic_socket.hpp:309:7
    #2 0x55d07dc4f106 in boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>::basic_stream_socket(boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>&&) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/basic_stream_socket.hpp:270:7
    #3 0x55d07dc485f7 in boost::asio::detail::move_binder2<boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>>, boost::system::error_code, boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>>::move_binder2(int, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>>&&, boost::system::error_code const&, boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>&&) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/bind_handler.hpp:873:7
    #4 0x55d07dc2fa05 in boost::asio::detail::io_uring_socket_move_accept_op<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>, boost::asio::detail::awaitable_handler<boost::asio::any_io_executor, boost::system::error_code, boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::io_context::basic_executor_type<std::allocator<void>, 0ul>>>, boost::asio::any_io_executor>::do_complete(void*, boost::asio::detail::scheduler_operation*, boost::system::error_code const&, unsigned long) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/io_uring_socket_accept_op.hpp:250:9
    #5 0x55d07dc41405 in boost::asio::detail::scheduler_operation::destroy() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/scheduler_operation.hpp:45:5
    #6 0x55d07dc43a82 in void boost::asio::detail::op_queue_access::destroy<boost::asio::detail::io_uring_operation>(boost::asio::detail::io_uring_operation*) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/op_queue.hpp:47:8
    #7 0x55d07dc43941 in boost::asio::detail::op_queue<boost::asio::detail::io_uring_operation>::~op_queue() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/op_queue.hpp:81:7
    #8 0x55d07dc438bc in boost::asio::detail::io_uring_service::io_queue::~io_queue() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/io_uring_service.hpp:57:9
    #9 0x55d07dc43846 in boost::asio::detail::io_uring_service::io_object::~io_object() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/io_uring_service.hpp:73:9
    #10 0x55d07dc437ce in void boost::asio::detail::object_pool_access::destroy<boost::asio::detail::io_uring_service::io_object>(boost::asio::detail::io_uring_service::io_object*) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/object_pool.hpp:47:5
    #11 0x55d07dc436cb in boost::asio::detail::object_pool<boost::asio::detail::io_uring_service::io_object>::destroy_list(boost::asio::detail::io_uring_service::io_object*) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/object_pool.hpp:156:7
    #12 0x55d07dc336ed in boost::asio::detail::object_pool<boost::asio::detail::io_uring_service::io_object>::~object_pool() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/object_pool.hpp:79:5
    #13 0x55d07dc33b29 in boost::asio::detail::io_uring_service::~io_uring_service() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/impl/io_uring_service.ipp:63:1
    #14 0x55d07dc33bc8 in boost::asio::detail::io_uring_service::~io_uring_service() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/impl/io_uring_service.ipp:58:1
    #15 0x55d07dc479ff in boost::asio::detail::service_registry::destroy(boost::asio::execution_context::service*) /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/impl/service_registry.ipp:110:3
    #16 0x55d07dc6524b in boost::asio::detail::service_registry::destroy_services() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/detail/impl/service_registry.ipp:54:5
    #17 0x55d07dc64dff in boost::asio::execution_context::destroy() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/impl/execution_context.ipp:46:22
    #18 0x55d07dc623b6 in boost::asio::execution_context::~execution_context() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/impl/execution_context.ipp:35:3
    #19 0x55d07dc1f498 in boost::asio::io_context::~io_context() /home/martin.beran/tmp/./boost_1_81_0/boost/asio/impl/io_context.ipp:58:1
    #20 0x55d07dc165d8 in main /home/martin.beran/tmp/bug.cpp:21:1
    #21 0x7f44811a6d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #22 0x7f44811a6e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #23 0x55d07dbecbe4 in _start (/home/martin.beran/tmp/bug+0x49be4) (BuildId: 3767a8c2e8673048d1b4af809f7194c9d66c14c7)

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior boost_1_81_0/boost/asio/detail/io_object_impl.hpp:70:15 in 

Without -D BOOST_ASIO_DISABLE_EPOLL, the program terminates normally and does not report UB.