Skip to content

WebSocket connection may abort due to unsafe use of basic_stream::expires_after() #564

@sophyphilo

Description

@sophyphilo

Describe the bug

When using ccapi WebSocket (WS/WSS) connections, the application may abort at runtime with a Boost.Beast assertion failure:

Assertion `!impl_->read.pending || !impl_->write.pending' failed

This crash is triggered by calling boost::beast::basic_stream::expires_after() while there are pending asynchronous read/write operations on the stream. This situation can occur during WebSocket connection establishment or automatic reconnection.

The issue originates from startConnectWs() in ccapi_service.h, where expires_after() is unconditionally called on the lowest-layer stream before async_connect().


To Reproduce

Steps to reproduce the behavior:

  1. Use ccapi with WebSocket (especially WSS) enabled
  2. Enable automatic reconnect or run under conditions with frequent reconnects / concurrent read-write activity
  3. Let the application run for some time (the crash is timing-dependent)
  4. Observe that the process aborts with a Boost.Beast assertion failure

Typical stack trace points to:

#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007aca83e4527e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007aca83e288ff in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007aca83e2881b in __assert_fail_base (fmt=0x7aca83fd01e8 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x7aca82e02d88 "! impl_->read.pending || ! impl_->write.pending", 
    file=file@entry=0x7aca82e02d48 "/home/mydeps/include/boost/beast/core/impl/basic_stream.hpp", line=line@entry=711, 
    function=function@entry=0x7aca82e02bd8 "void boost::beast::basic_stream< <template-parameter-1-1>, <template-parameter-1-2>, <template-parameter-1-3> >::expires_after(std::chrono::nanoseconds) [with Protocol = boost::asio::ip::tcp; Executor"...) at ./assert/assert.c:96
#6  0x00007aca83e3b517 in __assert_fail (assertion=0x7aca82e02d88 "! impl_->read.pending || ! impl_->write.pending", file=0x7aca82e02d48 "/home/mydeps/include/boost/beast/core/impl/basic_stream.hpp", 
    line=711, 
    function=0x7aca82e02bd8 "void boost::beast::basic_stream< <template-parameter-1-1>, <template-parameter-1-2>, <template-parameter-1-3> >::expires_after(std::chrono::nanoseconds) [with Protocol = boost::asio::ip::tcp; Executor"...) at ./assert/assert.c:105
#7  0x00007aca829b9b40 in boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>::expires_after (this=0x7ac9d40df0b0, 
    expiry_time=std::chrono::duration = { 10000000000ns }) at /home/mydeps/include/boost/beast/core/impl/basic_stream.hpp:711
#8  0x00007aca82947512 in ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}::operator()<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> > >(std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >&) const (__closure=0x7ac9a3ffa4b0, 
    streamPtr=std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true>> (use count 1, weak count 0) = {...}) at /data/XX/../API/ccapi_cpp/service/ccapi_service.h:1001
#9  0x00007aca82a1cc6a in std::__invoke_impl<void, ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}, std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >&>(std::__invoke_other, ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >&) (__f=...)
    at /usr/include/c++/13/bits/invoke.h:61
#10 0x00007aca829ed8bb in std::__invoke<ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}, std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >&>(ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >&) (__fn=...) at /usr/include/c++/13/bits/invoke.h:96
#11 0x00007aca829bcb94 in std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<std::__detail::__variant::__deduce_visit_result<void> (*)(ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&)>, std::integer_sequence<unsigned long, 0ul> >::__visit_invoke(ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&) (__visitor=..., 
    __vars#0=std::variant [index 0] containing std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true>> (use count 1, weak count 0) = {...}) at /usr/include/c++/13/variant:1060
#12 0x00007aca829bccbe in std::__do_visit<std::__detail::__variant::__deduce_visit_result<void>, ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&>(ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&) (__visitor=...) at /usr/include/c++/13/variant:1815
#13 0x00007aca829bcd35 in std::visit<ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&>(ccapi::Service::startConnectWs(std::shared_ptr<ccapi::WsConnection>, long, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)::{lambda(auto:1&)#1}&&, std::variant<std::shared_ptr<boost::beast::websocket::stream<boost::beast::ssl_stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy> >, true> >, std::shared_ptr<boost::beast::websocket::stream<boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>, true> > >&) (__visitor=...) at /usr/include/c++/13/variant:1878
#14 0x00007aca82947a37 in ccapi::Service::startConnectWs (this=0x7ac9a17fb020, wsConnectionPtr=std::shared_ptr<ccapi::WsConnection> (use count 3, weak count 0) = {...}, timeoutMilliseconds=10000, 
    tcpResolverResults=...) at /data/XX/../API/ccapi_cpp/service/ccapi_service.h:996
#15 0x00007aca829473cc in ccapi::Service::onResolveWs (this=0x7ac9a17fb020, wsConnectionPtr=std::shared_ptr<ccapi::WsConnection> (use count 3, weak count 0) = {...}, 
    newResolverPtr=std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor>> (use count 1, weak count 0) = {...}, ec=..., tcpNewResolverResultsWs=...)
    at /data/XX/API/ccapi_cpp/service/ccapi_service.h:992
#16 0x00007aca82bc1906 in std::__invoke_impl<void, void (ccapi::Service::* const&)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::ba--Type <RET> for more, q to quit, c to continue without paging--
sic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&> (
    __f=@0x7ac9a3ffa700: (void (ccapi::Service::*)(class ccapi::Service * const, class std::shared_ptr<ccapi::WsConnection>, class std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, class boost::system::error_code, class boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)) 0x7aca829472f2 <ccapi::Service::onResolveWs(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)>, __t=...)
    at /usr/include/c++/13/bits/invoke.h:74
#17 0x00007aca82bb4bdb in std::__invoke<void (ccapi::Service::* const&)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&> (
    __fn=@0x7ac9a3ffa700: (void (ccapi::Service::*)(class ccapi::Service * const, class std::shared_ptr<ccapi::WsConnection>, class std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, class boost::system::error_code, class boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)) 0x7aca829472f2 <ccapi::Service::onResolveWs(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>)>)
    at /usr/include/c++/13/bits/invoke.h:96
#18 0x00007aca82ba2a58 in std::_Mem_fn_base<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), true>::operator()<std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&> (this=0x7ac9a3ffa700)
    at /usr/include/c++/13/functional:170
#19 0x00007aca82b9090d in boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >::invoke<0ul, 1ul, 2ul, boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&> (
    this=0x7ac9a3ffaa90) at /home/mydeps/include/boost/beast/core/detail/bind_handler.hpp:235
#20 0x00007aca82b82cea in boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >::operator()<boost::system::error_code const&, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> const&> (
    this=0x7ac9a3ffaa90) at /home/mydeps/include/boost/beast/core/detail/bind_handler.hpp:258
#21 0x00007aca82b74e2b in boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >::operator() (
    this=0x7ac9a3ffaa90) at /home/mydeps/include/boost/asio/detail/bind_handler.hpp:164
#22 0x00007aca82b74da8 in boost::asio::asio_handler_invoke<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > > (function=...) at /home/mydeps/include/boost/asio/handler_invoke_hook.hpp:69
#23 0x00007aca82b630fc in boost::beast::detail::asio_handler_invoke<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >&> (f=..., op=0x7ac9a3ffaa90) at /home/mydeps/include/boost/beast/core/detail/bind_handler.hpp:272
#24 0x00007aca82b4bd39 in boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > > > (function=..., context=...) at /home/mydeps/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#25 0x00007aca82b2d3b8 in boost::asio::detail::asio_handler_invoke<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > (function=..., 
    this_handler=0x7ac9a3ffaa90) at /home/mydeps/include/boost/asio/detail/bind_handler.hpp:207
#26 0x00007aca82b12ad1 in boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > > (
    function=..., context=...) at /home/mydeps/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#27 0x00007aca82af7740 in boost::asio::detail::io_object_executor<boost::asio::executor>::dispatch<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_p--Type <RET> for more, q to quit, c to continue without paging--
tr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> >, std::allocator<void> > (this=0x7ac9a3ffaa80, f=..., a=...) at /home/mydeps/include/boost/asio/detail/io_object_executor.hpp:119
#28 0x00007aca82ad7343 in boost::asio::detail::handler_work<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::asio::detail::io_object_executor<boost::asio::executor>, boost::asio::detail::io_object_executor<boost::asio::executor> >::complete<boost::asio::detail::binder2<boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp> > >
    (this=0x7ac9a3ffaa70, function=..., handler=...) at /home/mydeps/include/boost/asio/detail/handler_work.hpp:72
#29 0x00007aca82ab5255 in boost::asio::detail::resolve_query_op<boost::asio::ip::tcp, boost::beast::detail::bind_front_wrapper<void (ccapi::Service::*)(std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> >, boost::system::error_code, boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>), std::shared_ptr<ccapi::Service>, std::shared_ptr<ccapi::WsConnection>, std::shared_ptr<boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::executor> > >, boost::asio::detail::io_object_executor<boost::asio::executor> >::do_complete (owner=0x6294ddd2a230, base=0x7ac99d988210) at /home/mydeps/include/boost/asio/detail/resolve_query_op.hpp:129
#30 0x00007aca828f03e6 in boost::asio::detail::scheduler_operation::complete (this=0x7ac99d988210, owner=0x6294ddd2a230, ec=..., bytes_transferred=0)
    at /home/mydeps/include/boost/asio/detail/scheduler_operation.hpp:40
#31 0x00007aca828f5f48 in boost::asio::detail::scheduler::do_run_one (this=0x6294ddd2a230, lock=..., this_thread=..., ec=...) at /home/mydeps/include/boost/asio/detail/impl/scheduler.ipp:447
#32 0x00007aca828f57c5 in boost::asio::detail::scheduler::run (this=0x6294ddd2a230, ec=...) at /home/mydeps/include/boost/asio/detail/impl/scheduler.ipp:200
#33 0x00007aca828f95d8 in boost::asio::io_context::run (this=0x6294ddd0ed10) at /home/mydeps/include/boost/asio/impl/io_context.ipp:63
#34 0x00007aca82937a70 in ccapi::ServiceContext::start()::{lambda()#1}::operator()() const (__closure=0x6294ddc8e518)
    at /data/XX/../API/ccapi_cpp/service/ccapi_service_context.h:73
#35 0x00007aca82df8321 in std::__invoke_impl<void, ccapi::ServiceContext::start()::{lambda()#1}>(std::__invoke_other, ccapi::ServiceContext::start()::{lambda()#1}&&) (__f=...)
    at /usr/include/c++/13/bits/invoke.h:61
#36 0x00007aca82df8049 in std::__invoke<ccapi::ServiceContext::start()::{lambda()#1}>(ccapi::ServiceContext::start()::{lambda()#1}&&) (__fn=...) at /usr/include/c++/13/bits/invoke.h:96
#37 0x00007aca82df7854 in std::thread::_Invoker<std::tuple<ccapi::ServiceContext::start()::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0x6294ddc8e518)
    at /usr/include/c++/13/bits/std_thread.h:292
#38 0x00007aca82df5fc6 in std::thread::_Invoker<std::tuple<ccapi::ServiceContext::start()::{lambda()#1}> >::operator()() (this=0x6294ddc8e518) at /usr/include/c++/13/bits/std_thread.h:299
#39 0x00007aca82df3770 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<ccapi::ServiceContext::start()::{lambda()#1}> > >::_M_run() (this=0x6294ddc8e510)
    at /usr/include/c++/13/bits/std_thread.h:244
#40 0x00007aca842ecdb4 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#41 0x00007aca83e9caa4 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:447
#42 0x00007aca83f29c6c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

Expected behavior

The application should not abort due to an internal assertion when managing WebSocket connections.

Timeout handling for WebSocket connections should be safe even when:

  • there are pending asynchronous read/write operations
  • WebSocket reconnect logic is active
  • concurrent WebSocket I/O is occurring

At minimum, ccapi should avoid calling basic_stream::expires_after() in a way that violates Boost.Beast usage constraints.


Screenshots

N/A (runtime assertion failure / abort)


Additional context

  • Root cause
    boost::beast::basic_stream::expires_after() must not be called while there are pending async read/write operations. Boost.Beast enforces this with a hard assertion and calls abort().

  • Location in code
    File: include/ccapi_cpp/service/ccapi_service.h
    Function: Service::startConnectWs

    if (timeoutMilliseconds > 0) {
      beast::get_lowest_layer(*streamPtr)
          .expires_after(std::chrono::milliseconds(timeoutMilliseconds));
    }
    

-Why this is problematic:
In WebSocket / SSL / reconnect scenarios, the stream may already have pending I/O (e.g. leftover read/write operations or concurrent operations), making this call unsafe.

-Suggested fix:

Remove usage of basic_stream::expires_after() for WebSocket connections, and

Use websocket::stream_base::timeout::suggested(role_type::client) for WebSocket timeouts, or

Manage connect timeouts via an external asio::steady_timer instead.

Environment:

OS: Linux (Ubuntu)

Compiler: GCC 13.x

Boost: uses Boost.Beast / Boost.Asio

ccapi: current master branch (commit at time of report)

Crash signal: SIGABRT

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions