Hi Michael:Hello, my question is about the error code returned by io_service.run_one. I expect the error code returned by run_one to be the same as the one in the handler - but they are not. Inside my handler I check the error code, which is equal to operation aborted: void ConnectionBase::ReadUntilHandler( const boost::system::error_code & ec, std::size_t bytes_transferred) { // ec == boost::asio::error::operation_aborted ... } At some other point I call io_service.run_one, which calls the above handler: ... m_asioService.run_one(ec); assert(ec == boost::asio::error::operation_aborted); ... The assertion fails - for some reason the error code is not the same as in the handler. What's the reason for this? Maybe my assumtion that run_one(ec) returns the error code of the handler is simply wrong? If so, what error does io_service.run(ec) actually report? Thanks for help, Michael PS: boost::asio version is 1.56.0 _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
The function boost:system:system_category() returns a reference
to a local static variable, system_category_const. When built as
header only (-DBOOST_ERROR_CODE_HEADER_ONLY) the function is
declared as inlined and the optimizer fails to ensure a single
value is returned by this function within a translation unit. It
is conceptually the same as the issue discussed here:
http://processors.wiki.ti.com/index.php/C++_Inlining_Issues
under the section "Static Variables in Inline Functions".
This manifests itself in the following expression from
boost:asio:detail:impl:socket_ops.ipp:non_blocking_recv():
if (ec == boost::asio::error::would_block || ec == boost::asio::error::try_again) return false;
that evaluates to false when it should evaluate to true.
Ultimately this causes the io_service to invoke the socket's ready
handler rather than continuing to poll the socket waiting for
data.
The inequality stems from the implicit conversion of the
enumerates to error_code instances, during which calls to
system_category() used to set error_code:m_cat, return differing
values.
The problem disappears if either the error handling code is not
built header only as this results in a single definition of
system_category() supplied by libboost_system; or the error
handling code is not optimized.
From testing it appears that the issue began in GCC 5.2.0 and exists through 5.3.1, the latest released version. GCC 6.0 is nearing release and will have to be tested.
We reported this both GCC and Boost:https://svn.boost.org/trac/boost/ticket/11989
ec.value() == boost::asio::error::operation_abortedBy comparing ec.value() to the enum, you eliminate the implicit conversion of the enum to an error_code instance and thereby skirt the issue of the m_cat members not being equal when they should be. In reality, you only care about the error value, error_code:m_val, anyway.