Boost logo

Boost Users :

Subject: Re: [Boost-users] Compare boost::system::error_category
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-03-25 23:05:40


>>>> Boost's quality of implementation is the same as libstdc++ or libc++,
>>>> you can get multiple instantiations in certain circumstances and those
>>>> can have differing addresses.
>>>
>>> The various error categories are implemented (for header-only libraries)
>>> as inlined Meyer singletons. Does that mean that we have a general
>>> problem with such singletons?
>>
>> The short answer is yes, the error category comparison operators are
>> unreliable on all major STLs apart from Dinkumware's and in Boost.
>
> Can you elaborate on what the core problem is?

To generate ELF object A using header only library X which defines a
custom error category, the linker chooses any one of the implementations
of that error category in the object files linked as it is marked weak
due to being inline. Due to use of -fvisibility=hidden, symbol for
custom error category is not exported.

To generate ELF object B using header only library X which defines a
custom error category, the linker chooses any one of the implementations
of that error category in the object files linked as it is marked weak
due to being inline. Due to use of -fvisibility=hidden, symbol for
custom error category is not exported.

Program C links against ELF object A and ELF object B. There are now two
instances of the same category object, and their addresses will not
equal. Possible solution: Mark custom error category retrieval function
with default visibility?

That will work with RTLD_GLOBAL. But what if a SO is loaded with
RTLD_LOCAL? That establishes multiple global symbol tables, and once
again two instances of the same error category appear.

The exact same problem applies to the RTTI used to catch exception
throws. The problem was fixed on libstdc++ by using string comparison to
compare RTTI if address comparison failed. libc++ used to noisily take a
stand against string comparison and insist on address comparison, but
they may since have buckled under the constant bugs about exceptions not
being caught.

> You have mentioned both memory barriers and RTLD_LOCAL which seem to
> imply different problems (concurrency versus relocation of weak
> symbols.)

MSVC has the advantage of controlling its ABI. They invented a thing
called _Immortalize which gets specially treated by the linker to
instantiate exactly one of the thing ever in a process. As the VS2015
source file says, /* MAGIC */. Because multiple threads could reach the
instantiation concurrently, it needs to be a memory barrier so one gets
chosen and the others wait.

> Please notice that I am interested in singletons in general, not only
> error categories.

PE and MachO are the least affected by this problem because their
creators thought of symbol encapsulation in advance. ELF is severely
affected by it. The fault is in the ELF spec which assumes a globally
visible unique symbol table. I have tried raising this problem with
those responsible for ELF on a number of occasions in the past, it was
considered not a problem for the linker and ELF folk, they felt it was a
C++ problem. Attempting to explain this was not a problem in PE nor
MachO nor many other binary formats got me nowhere.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net