Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::system::error_code::message() throwing access violation exception with boost::asio socket

I am implementing a client application that has to make a small number of socket connections to hardware devices. I have broken down the problem to the following small code subset

boost::system::error_code ec;
std::string str_message = ec.message();  // no access violation before connect()
std::string str_port = "502";
std::string str_ip = "192.168.12.198";

boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(),str_ip,str_port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::socket s(io_service);

ec = s.connect(*iterator,ec);
if (ec)
{
    // connection error of some kind.
    std::string str_debug = ec.message();  // BANG!!!!

}

I am using Embarcadero RAD studio XE4 C++ Builder and when I run the above code in the main VCL thread it works fine. When I run it with multiple connections, I have the above code running in multiple instances of the TThread class and that is when I get into problems with an access violation - it appears that when the error_code is modified by the connect call, the internal member m_cat of the error_code instance becomes NULL and so when I call message() I get the access violation. This happens even when I just have a single background thread running.

Is it possible that my code above is simply not thread safe in the way I need to use it? I have tried to find out why this code won't run in a background thread, but cannot find anything about it.

The boost version I am running is 1.50 as this is the integrated version that is used for building 64 bit applications in RAD studio.

Has anyone else encountered this issue in a multithreaded setting (in Embarcadero or otherwise) and if so how did you resolve it? Or is this class simply not safe to use in a multithreaded way?

like image 968
mathematician1975 Avatar asked Jan 29 '14 19:01

mathematician1975


People also ask

What error reporting does boost system support?

The Boost System library supports both error reporting by exception and by error code. In addition to portable errors codes and conditions supported by the error_code.hpp header, system-specific headers support the Cygwin, Linux, and Windows platforms. These headers are effectively no-ops if included for platforms other than their intended target.

What is boost system library?

The Boost System library provides simple, light-weight error_code objects that encapsulate system-specific error code values, yet also provide access to more abstract and portable error conditions via error_condition objects.

What is the difference between boost_system_use_utf8 and CP_ACP?

When BOOST_SYSTEM_USE_UTF8 is defined, on Windows the library returns UTF-8 messages using code page CP_UTF8 instead of the default CP_ACP . This macro has no effect on POSIX. In the process of adding Boost.System to the C++11 standard library, the C++ committee changed some names.

What version of C++ do I need to link to boost?

In 1.68, code using any C++ standard can link with Boost.System built with C++14 or above, but if Boost.System is built with C++11 or below, only code also built with C++11 and below can link to it successfully.)


1 Answers

This is kind of a long shot, but it might be worth a try:

The system::error_code is made up of two entries: An error value and a category. The error value is basically just an int, but the category is a Singleton. This is required because error categories are compared for equality based on pointer identities (ie. two categories are equal if and only if they point to the same category object).

The problem is that initialization of the category Singleton might not be thread-safe. Asio uses the system_category, which is implemented in boost/libs/system/src/error_code.cpp. For 1.50 the implementation looks like this:

BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT
{
  static const system_error_category  system_category_const;
  return system_category_const;
}

This is guaranteed to be thread-safe on C++11 conforming compilers, but if your compiler does not implement thread-safe initialization of function-scope statics, this might break. You can easily verify this by tracing calls to this function and see if you observe a potential race.

like image 196
ComicSansMS Avatar answered Sep 21 '22 13:09

ComicSansMS