Mir

Comment 6 for bug 1391976

Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Re: Loading libmircommon.so twice leads to a segfault in libprotobuf.so

Analysis
--------

The core of the problem is that it's not safe to reuse libprotobuf after
calling google::protobuf::ShutdownProtobufLibrary() without unloading and
reloading the library first. Note that libraries/executables that use protobuf
(e.g. libmirprotobuf) use libprotobuf code also during static initialization,
that's why we see the issue when just loading/unloading these libraries.

libprotobuf uses flags to ensure initialization code is run once (see
GoogleInitOnce() and friends), but these flags are not reset during shutdown.
So, if the library is not reloaded and we try to call libprotobuf code
after shutdown, the code thinks that everything is already initialized and
ends up accessing data structures that have been deallocated.

In the scenario described in the bug, libprotobuf is not unloaded when
unloading the mir libraries because libstdc++ is bound to (i.e., needs a symbol from)
libprotobuf. libprotobuf contains an instantiation of a string template
function [1] from the standard c++ library and exports that instantiation as a
weak symbol (as expected). libstdc++ itself also needs the same template
function instantiation, and the linker resolves the symbol by choosing the
instantiation from libprotobuf (which is acceptable behavior).

Proposed solution
-----------------

Ensure libprotobuf can be reused after shutdown by properly resetting "once"
flags on ShutdownProtobufLibrary(). First experiments are promising, but "once"
flags are used extensively in the code base and also in generated code, so
great care needs to be taken. It's also not known if upstream is willing to
accept such patches.

[1] _ZNSs12_S_constructIPcEES0_T_S1_RKSaIcESt20forward_iterator_tag