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?
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.
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.
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.
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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With