asio icon indicating copy to clipboard operation
asio copied to clipboard

In class cancellation_signal (cancellation_signal.hpp) handler_ is freed but emit is called after being freed and causes a crash

Open sldr opened this issue 1 year ago • 0 comments

Environment Info

This is happening with Asio V1.29.0 (non-Boost) on Windows 10. I have also tried using the code from master and it still causes the crash.

I compile with Visual Studio 2022 V17.8.3 and /std:C++20. I am using coroutines and the following experimental classes:

  • awaitable_operators
  • concurrent_channel

Brief Description of Asio Usage

A std::thread is using the asio::concurrent_channel to send a std::sting to coroutines running in an asio::thread_pool. The thread pool size is 2. An asio coroutine is started using asio::co_spawn that after opening a socket does a

co_await (s->async_wait(asio::ip::tcp::socket::wait_read, asio::use_awaitable) || concurrent_channel->async_receive(asio::use_awaitable))

and then reads data from socket or processes std::string from concurrent_channel.

Crash Details

This is emit method from cancellation_signal where handler_ is nullptr and the dereference of handler_ is done for call method.:

  /// Emits the signal and causes invocation of the slot's handler, if any.
  void emit(cancellation_type_t type)
  {
    if (handler_)
      handler_->call(type);
  }

Visual Studio showing the nullptr value for handler_: image

Call Stack

ucrtbased.dll!issue_debug_notification(const wchar_t * const message) Line 28	
ucrtbased.dll!__acrt_report_runtime_error(const wchar_t * message) Line 154	
ucrtbased.dll!abort() Line 61	
vcruntime140d.dll!_purecall() Line 30	
MyProg.exe!asio::cancellation_signal::emit(asio::cancellation_type type) Line 99	
MyProg.exe!asio::cancellation_state::impl<asio::cancellation_filter<1>,asio::cancellation_filter<1>>::operator()(asio::cancellation_type in) Line 222	
MyProg.exe!asio::detail::cancellation_handler<asio::cancellation_state::impl<asio::cancellation_filter<1>,asio::cancellation_filter<1>>>::call(asio::cancellation_type type) Line 56	
MyProg.exe!asio::cancellation_signal::emit(asio::cancellation_type type) Line 99	
MyProg.exe!asio::detail::co_spawn_cancellation_handler<asio::experimental::detail::parallel_group_op_handler<1,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,void>::operator()(asio::cancellation_type type) Line 279	
MyProg.exe!asio::detail::cancellation_handler<asio::detail::co_spawn_cancellation_handler<asio::experimental::detail::parallel_group_op_handler<1,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,void>>::call(asio::cancellation_type type) Line 56	
MyProg.exe!asio::cancellation_signal::emit(asio::cancellation_type type) Line 99	
MyProg.exe!asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>::operator()<std::exception_ptr>(std::exception_ptr <args_0>) Line 225	
MyProg.exe!asio::detail::co_spawn_entry_point::__l2::<lambda_1>::operator()() Line 207	
MyProg.exe!asio::detail::binder0<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>>::operator()() Line 56	
MyProg.exe!asio::detail::executor_function::complete<asio::detail::binder0<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>>,std::allocator<void>>(asio::detail::executor_function::impl_base * base, bool call) Line 112	
MyProg.exe!asio::detail::executor_function::operator()() Line 62	
MyProg.exe!asio::io_context::basic_executor_type<std::allocator<void>,4>::execute<asio::detail::executor_function>(asio::detail::executor_function && f) Line 282	
MyProg.exe!asio::execution::detail::any_executor_base::execute_ex<asio::io_context::basic_executor_type<std::allocator<void>,4>>(const asio::execution::detail::any_executor_base & ex, asio::detail::executor_function && f) Line 900	
MyProg.exe!asio::execution::detail::any_executor_base::execute<asio::detail::binder0<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>>>(asio::detail::binder0<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>> && f) Line 680	
MyProg.exe!asio::detail::initiate_dispatch_with_executor<asio::any_io_executor>::operator()<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>>(asio::detail::co_spawn_entry_point::__l2::<lambda_1> && handler, void * __formal, void * __formal) Line 105	
MyProg.exe!??@e461c3c8f1d18d37e393182ac754932e@(asio::detail::initiate_dispatch_with_executor<asio::any_io_executor> && initiation, asio::detail::co_spawn_entry_point::__l2::<lambda_1> && token) Line 275	
MyProg.exe!asio::async_initiate<`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>,void __cdecl(void),asio::detail::initiate_dispatch_with_executor<asio::any_io_executor>>(asio::detail::initiate_dispatch_with_executor<asio::any_io_executor> && initiation, asio::detail::co_spawn_entry_point::__l2::<lambda_1> & token) Line 573	
MyProg.exe!asio::dispatch<asio::any_io_executor,`asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>'::`2'::<lambda_1>>(const asio::any_io_executor & ex, asio::detail::co_spawn_entry_point::__l2::<lambda_1> && token, int __formal) Line 155	
MyProg.exe!asio::detail::co_spawn_entry_point<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>>(asio::awaitable<void,asio::any_io_executor> * $FP2, asio::detail::co_spawn_state<asio::experimental::detail::parallel_group_op_handler<0,asio::experimental::wait_for_one_success,asio::detail::awaitable_async_op_handler<void __cdecl(std::array<unsigned __int64,2>,std::exception_ptr,std::exception_ptr,std::string),asio::any_io_executor>,asio::deferred_async_operation<void __cdecl(std::exception_ptr),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<void,asio::any_io_executor>>,asio::deferred_async_operation<void __cdecl(std::exception_ptr,std::string),asio::detail::initiate_co_spawn<asio::any_io_executor>,asio::detail::awaitable_as_function<std::string,asio::any_io_executor>>>,asio::any_io_executor,asio::detail::awaitable_as_function<void,asio::any_io_executor>,void> s) Line 203	
MyProg.exe!std::coroutine_handle<void>::resume() Line 85	
MyProg.exe!asio::detail::awaitable_frame_base<asio::any_io_executor>::resume() Line 501	
MyProg.exe!asio::detail::awaitable_thread<asio::any_io_executor>::pump() Line 769	
MyProg.exe!asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>::operator()(const std::error_code & ec) Line 93	
MyProg.exe!asio::detail::binder1<asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>,std::error_code>::operator()() Line 116	
MyProg.exe!asio::detail::handler_work<asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>,asio::any_io_executor,void>::complete<asio::detail::binder1<asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>,std::error_code>>(asio::detail::binder1<asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>,std::error_code> & function, asio::detail::awaitable_handler<asio::any_io_executor,std::error_code> & handler) Line 433	
MyProg.exe!asio::detail::win_iocp_wait_op<asio::detail::awaitable_handler<asio::any_io_executor,std::error_code>,asio::any_io_executor>::do_complete(void * owner, asio::detail::win_iocp_operation * base, const std::error_code & result_ec, unsigned __int64 __formal) Line 112	
MyProg.exe!asio::detail::win_iocp_operation::complete(void * owner, const std::error_code & ec, unsigned __int64 bytes_transferred) Line 47	
MyProg.exe!asio::detail::win_iocp_socket_service_base::reactor_op_cancellation::do_complete(void * owner, asio::detail::win_iocp_operation * base, const std::error_code & result_ec, unsigned __int64 bytes_transferred) Line 762	
MyProg.exe!asio::detail::win_iocp_operation::complete(void * owner, const std::error_code & ec, unsigned __int64 bytes_transferred) Line 47	
MyProg.exe!asio::detail::win_iocp_io_context::do_one(unsigned long msec, asio::detail::win_iocp_thread_info & this_thread, std::error_code & ec) Line 475	
MyProg.exe!asio::detail::win_iocp_io_context::run(std::error_code & ec) Line 205	
MyProg.exe!asio::io_context::run() Line 63	
MyProg.exe!pac::PortASIOCtx::getIOContext::__l48::<lambda_1>::operator()() Line 998	
MyProg.exe!asio::detail::binder0<`pac::PortASIOCtx::getIOContext'::`48'::<lambda_1>>::operator()() Line 56	
MyProg.exe!asio::detail::executor_op<asio::detail::binder0<`pac::PortASIOCtx::getIOContext'::`48'::<lambda_1>>,std::allocator<void>,asio::detail::scheduler_operation>::do_complete(void * owner, asio::detail::scheduler_operation * base, const std::error_code & __formal, unsigned __int64 __formal) Line 69	
MyProg.exe!asio::detail::scheduler_operation::complete(void * owner, const std::error_code & ec, unsigned __int64 bytes_transferred) Line 40	
MyProg.exe!asio::detail::scheduler::do_run_one(asio::detail::conditionally_enabled_mutex::scoped_lock & lock, asio::detail::scheduler_thread_info & this_thread, const std::error_code & ec) Line 493	
MyProg.exe!asio::detail::scheduler::run(std::error_code & ec) Line 209	
MyProg.exe!asio::thread_pool::thread_function::operator()() Line 38	
MyProg.exe!asio::detail::win_thread::func<asio::thread_pool::thread_function>::run() Line 122	
MyProg.exe!asio::detail::win_thread_function(void * arg) Line 126	
ucrtbased.dll!thread_start<unsigned int (__cdecl*)(void *),1>(void * const parameter) Line 97	
kernel32.dll!BaseThreadInitThunk()	Unknown
ntdll.dll!RtlUserThreadStart()	Unknown

Notes

  • I have written a small peiece of code to try to repro the issue but have not been able to get it to reproduce with the snipit. Reproducing with the full program sometimes takes a while.
  • I have a dump file from Windows but can't make that public.
  • Issue #1332 seems to be a similar issue.

Thanks, SLDR (Stephen L. De Rudder)

sldr avatar Dec 22 '23 00:12 sldr