[asio] Error code by io_service.run(ec) not the same as in async_read_handler
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
On 4/6/16 5:58 AM, Michael Weise wrote:
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 Hi Michael:
Are you compiling header only and If so are you using GCC 5.2 or newer with optimization enabled (-O2) ? If so then you may be hitting this issue: 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://gcc.gnu.org/bugzilla/show_bug.cgi?id=69789 https://svn.boost.org/trac/boost/ticket/11989 If this is indeed your issue you could try any of the following: 1. Change your handler's comparison to this: ec.value() == boost::asio::error::operation_aborted By 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. 2. Rather than compile header only, link to boost system lib. 3. Do not compile with optimization, -gO0 Thomas Markwalder ISC Software Engineering
participants (2)
-
Michael Weise
-
Thomas Markwalder