asio
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
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_:
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)