Subject: Re: [Boost-bugs] [Boost C++ Libraries] #2217: serialization 1.36.0 extended_type_info exit issue(s)
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2008-09-12 19:51:35
#2217: serialization 1.36.0 extended_type_info exit issue(s)
-----------------------------------+----------------------------------------
Reporter: timothysc_at_[hidden] | Owner: ramey
Type: Bugs | Status: closed
Milestone: Boost 1.37.0 | Component: serialization
Version: Boost 1.36.0 | Severity: Problem
Resolution: fixed | Keywords: extended_type_info
-----------------------------------+----------------------------------------
Comment(by Ross Lippert <ross.lippert_at_[hidden]>):
While I believe that the iterator invalidation issues were important for
this problem, this issue should be reopened, because the story does not
end there.
I believe that the 1.36 implementation of extended_type_info_typeid
suffers from a static destructor fiasco. In particular, the tkmap
singleton which is local to the extended_type_info_typeid.cpp file,
functioning as a registry of type info, can be accessed by typeid
destructors after the tkmap has been destructed.
I have not been able to produce a small example, and I doubt that any
example I could produce would behave likewise across gcc versions.
However, I did instrument my code well enough to make a solid case.
It began with
{{{
*** glibc detected *** free(): invalid pointer: 0x00002b3004540dc0 ***
}}}
at exit.
Running the program in valgrind produced, as the first error,
{{{
==20744== Invalid read of size 8
==20744== at 0x5DC69BC:
std::_Rb_tree<boost::serialization::detail::extended_
type_info_typeid_0 const*,
boost::serialization::detail::extended_type_info_type
id_0 const*,
std::_Identity<boost::serialization::detail::extended_type_info_typ
eid_0 const*>, boost::serialization::detail::type_compare,
std::allocator<boost:
:serialization::detail::extended_type_info_typeid_0 const*>
>::lower_bound(boost
::serialization::detail::extended_type_info_typeid_0 const* const&)
(stl_tree.h:
1371)
==20744== by 0x5DC673A:
boost::serialization::detail::extended_type_info_typeid_0::type_unregister()
(stl_multiset.h:451)
==20744== by 0x40DA49: __tcf_12 (extended_type_info_typeid.hpp:85)
==20744== by 0x3759830CD4: exit (in /lib64/tls/libc-2.3.4.so)
==20744== by 0x375981C4C1: (below main) (in /lib64/tls/libc-2.3.4.so)
==20744== Address 0x6EE09B0 is 32 bytes inside a block of size 40 free'd
==20744== at 0x4905D7A: operator delete(void*)
(vg_replace_malloc.c:244)
==20744== by 0x5DC6D37:
std::_Rb_tree<boost::serialization::detail::extended_type_info_typeid_0
const*, boost::serialization::detail::extended_type_info_typeid_0
const*,std::_Identity<boost::serialization::detail::extended_type_info_typeid_0const*>,
oost::serialization::detail::type_compare,
std::allocator<boost::serialization::detail::extended_type_info_typeid_0
const*>>::_M_erase(std::_Rb_tree_node<boost::serialization::detail::extended_type_info_typeid_0
const*>*) (new_allocator.h:94)
==20744== by 0x5DC63E8: __tcf_0 (stl_tree.h:578)
==20744== by 0x3759830FBA: __cxa_finalize (in /lib64/tls/libc-2.3.4.so)
==20744== by 0x5DC6242: (within
/d/en/lippertr-0/p4/desmond/desmond2_lippertr/base/objs/Linux/x86_64/Release/lib/libdesmond_util.so)
==20744== by 0x5E46AE0: (within
/d/en/lippertr-0/p4/desmond/desmond2_lippertr/base/objs/Linux/x86_64/Release/lib/libdesmond_util.so)
==20744== by 0x3759830CD4: exit (in /lib64/tls/libc-2.3.4.so)
==20744== by 0x375981C4C1: (below main) (in /lib64/tls/libc-2.3.4.so)
}}}
As we see, the underlying rep of the tkmap is corrupt or invalid because
lower_bound is failing (this version of 1.36 includes the patches already
mentioned).
With a little bit of effort, I recompiled boost serialization to have a
destructor for the tkmap which prints to the screen and put print messages
in the extended_type_info_typeids.
{{{
in typeid destructor
unregistering m_key= 0x5f6ef20
N71_GLOBAL__N_desmond_src_util_timekeeper_timekeeper.cxx_00000000_435F3CA51_E
done unregistering.
done destructor.
tkmap is destroyed!
in typeid destructor
unregistering m_key= 0x517220 N3Ark3arkE
==20744== Invalid read of size 8
. . .
}}}
My subsequent prints show that the tkmap is being destructed in the middle
of a series of extended_type_info_typeid destructions. This is the static
destructor fiasco. The initializer fiasco is overcome by the usual
function-scoped static trick, but destructor calls are not so easily
serialized. When a destructor has to talk to an instance of another
object, you have to be sure that object hasn't destructed yet.
To further test, I altered the tkmap implementation to set a live bit.
{{{
(in extended_type_info_typeid.cpp
struct tkmap : std::multiset<
const extended_type_info_typeid_0 *,
type_compare
> {
static int live;
tkmap() { live=1; }
~tkmap() { live=0; std::cerr << "tkmap is destroyed!" << std::endl; }
};
int tkmap::live=0;
}}}
and added
{{{
if (!tkmap::live) return;
}}}
to the type_unregister method.
{{{
in typeid destructor
unregistering m_key= 0x5f6ef40
N71_GLOBAL__N_desmond_src_util_timekeeper_timekeeper.cxx_00000000_435F3CA51_E
done unregistering.
done destructor.
tkmap is destroyed!
in typeid destructor
unregistering m_key= 0x517220 N3Ark3arkE
done destructor.
in typeid destructor
unregistering m_key= 0x517ec0 N7Desmond6EngineE
done destructor.
==21051==
==21051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 9 from 4)
}}}
I believe that this makes for a substantial case that the addition of
tkmap to boost 1.36 (not in 1.35) needs to be rethought.
-- Ticket URL: <http://svn.boost.org/trac/boost/ticket/2217#comment:7> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:49:58 UTC