[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#247793: some thoughts



What seems to be happening is this:
arts_init() loads libartscbackend through lt_dlopen()
arts_free() unloads it through lt_dlclose()
arts_init() loads it again

When libartscbackend is loaded various other libraries it depends on are
loaded too, including in particular libkmedia2_idl, libartsflow and libmcop.
The dynamic linker keeps track of all these through reference counting so
when libartscbackend is unloaded, the reference count on libkmedia2_idl goes
down to zero and it is unloaded too.  Then when the second call to
arts_init() reloads libartscbackend, libkmedia2_idl is also loaded again,
(usually) at a different address.

However during the loading of libmcop, it uses (probably indirectly) the
_Rb_tree_rebalance (and some related) functions declared inline in
stl_tree.h which the linker resolves, producing the following output from
LD_DEBUG=files,bindings,symbols ./a.out:
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=./a.out
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/lib/tls/libdl.so.2
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libartsc.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/lib/tls/libpthread.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libgmodule-2.0.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libgthread-2.0.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libglib-2.0.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/lib/tls/libc.so.6
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/lib/ld-linux.so.2
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libartscbackend.so.0
     20398:     symbol=_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_;
lookup in file=/usr/lib/libartsflow.so.1
     20398:     file=/usr/lib/libartsflow.so.1;  needed by
/usr/lib/libmcop.so.1 (relocation dependency)
     20398:     binding file /usr/lib/libmcop.so.1 to
/usr/lib/libartsflow.so.1: normal symbol
_ZSt18_Rb_tree_rebalancePSt18_Rb_tree_node_baseRS0_'

What appears to be happening here is that because libartsflow is loaded
before libmcop and contains the symbol _Rb_tree_rebalance (which is really
part of STL anyway) the linker finds it there and doesn't bother looking in
libmcop itself, where it can also be found.  Then it concludes that libmcop
depends on libartsflow as well as the other way about; and thanks to this
circular dependency the reference count on these libraries can never drop to
zero, so they are not unloaded/reloaded during arts_free() and the second
arts_init().

When libkmedia2_idl is first loaded, the constructor for
static Arts::IDLFileReg IDLFileReg_kmedia2
is called (this object is declared in obj-i386-linux/soundserver/kmedia2.cc,
generated by mcopidl).  IDLFileReg inherits from StartupClass, and its
constructor calls StartupManager::Add so that a pointer to
IDLFileReg_kmedia2 is added into StartupManager::startupClasses (declared in
mcop/startupmanager.cc).  This variable is in libmcop and so as this library
is not unloaded/reloaded it is not destroyed and created again.  Hence it
retains the pointer to IDLFileReg_kmedia2 which however is invalid once
libkmedia2_idl has been unloaded and reloaded at a different address,
causing the segfault whenever StartupManager::startup() (the second time)
tries to access it.

This is primarily a description of what I have found out about this bug
so that it might help anybody else interested: at present I have not enough
understanding to actually suggest a fix.

-- 
Martin Orr
Linux Administrator,
Methodist College Belfast



Reply to: