Re: [boost] [1.37.0][serialization] Assertion failed at libs/serialization/src/extended_type_info.cpp:92

Robert, Would it be possible to get an answer to my initial questions, please? Thanks! Regards Hartmut
Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for polymorphic objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change the related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
To:
assert(start != end);
// remove entry in map which corresponds to this type while(start != end) { if(this == *start) x.erase(start++); else ++start; }
Which wouldn't remove the problem, but at least avoids hanging the program if assertions are off...
Regards Hartmut

When I look at the code I can explain what I had in mind. The ktmap ([export]key - type)map should have an entry for each instance of an exported type. These entries are static variables. So, when one of these static items are destroyed, its ktmap entry should be erased. The assertion is meant to trap a the case where the key isn't found in the map. Such a circumstance would indicate the map has become out of sync with the variable involved. In the absense of multi-threading should never happen. The code subsequent to the assertion presumes that at least one entry exists in the ktmap (do ...) so the assertion was there to detected an error in this presumption. So trapping on this condition inidicates that there must be an error somewhere else. I would expect that this is somewhere in the library rather than in the user's program. I could implement your suggestion, but I would much rather get to the bottom of it. dlopen(RTLD_GLOBAL|RTLD_LAZY) suggests to me that dlls are being loaded/unloaded outside of your control. The serialization library presumes that dlls are not loaded/unloaded but more than one thread at at time. Its concievable that this might be an issue. Robert Ramey Hartmut Kaiser wrote:
Robert,
Would it be possible to get an answer to my initial questions, please?
Thanks! Regards Hartmut
Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for polymorphic objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change the related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
To:
assert(start != end);
// remove entry in map which corresponds to this type while(start != end) { if(this == *start) x.erase(start++); else ++start; }
Which wouldn't remove the problem, but at least avoids hanging the program if assertions are off...
Regards Hartmut
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Robert, Thanks for your response.
When I look at the code I can explain what I had in mind.
The ktmap ([export]key - type)map should have an entry for each instance of an exported type. These entries are static variables. So, when one of these static items are destroyed, its ktmap entry should be erased. The assertion is meant to trap a the case where the key isn't found in the map. Such a circumstance would indicate the map has become out of sync with the variable involved. In the absense of multi-threading should never happen.
The code subsequent to the assertion presumes that at least one entry exists in the ktmap (do ...) so the assertion was there to detected an error in this presumption. So trapping on this condition inidicates that there must be an error somewhere else. I would expect that this is somewhere in the library rather than in the user's program.
I could implement your suggestion, but I would much rather get to the bottom of it.
Sure, understand. The problem is that in release mode my application just hangs indefinitely after main() exited and there is no way of terminating it short of kill -9. Not something I can ask my users to do all the time.
dlopen(RTLD_GLOBAL|RTLD_LAZY) suggests to me that dlls are being loaded/unloaded outside of your control. The serialization library presumes that dlls are not loaded/unloaded but more than one thread at at time. Its concievable that this might be an issue.
The shared libraries are loaded/unloaded in a fully controlled way at well defined points. Additionally, no multithreading is involved at the point of loading the libraries. Unloading happens after main() exited, so multithreading isn't an issue there either. The only reason why I wrote about dlopen(RTLD_GLOBAL|RTLD_LAZY) was that it just didn't work at all when I was using other flags (especially RTDL_LOCAL and RTDL_DEEPBIND mess things up - which is worth mentioning in the docs as it took me a couple of days to figure this out). A bit more detail about how I set things up: I'm serializing polymorphic objects through a shared_ptr to the base class. The object definitions are distributed over several shared libraries, all of them loaded using dlopen (on Windows 32/64Bit everything is fine, BTW). Each object has a corresponding BOOST_CLASS_EXPORT() placed in one of the cpp files each (not the headers) of the corresponding shared library. Boost serialization is linked dynamically (to ensure to have one typeinfo registry) as well, but the corresponding shared (boost) library is linked with the application, so it is loaded at application startup. Regards Hartmut
Robert Ramey
Robert,
Would it be possible to get an answer to my initial questions,
Hartmut Kaiser wrote: please?
Thanks! Regards Hartmut
Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for polymorphic objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change the related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
To:
assert(start != end);
// remove entry in map which corresponds to this type while(start != end) { if(this == *start) x.erase(start++); else ++start; }
Which wouldn't remove the problem, but at least avoids hanging the program if assertions are off...
Regards Hartmut
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hartmut Kaiser wrote:
Robert,
Sure, understand. The problem is that in release mode my application just hangs indefinitely after main() exited and there is no way of terminating it short of kill -9. Not something I can ask my users to do all the time.
In a pinch, you can tweak your copy of the library while this gets sorted out.
A bit more detail about how I set things up:
I'm serializing polymorphic objects through a shared_ptr to the base class. The object definitions are distributed over several shared libraries, all of them loaded using dlopen (on Windows 32/64Bit everything is fine, BTW). Each object has a corresponding BOOST_CLASS_EXPORT() placed in one of the cpp files each (not the headers) of the corresponding shared library. Boost serialization is linked dynamically (to ensure to have one typeinfo registry) as well, but the corresponding shared (boost) library is linked with the application, so it is loaded at application startup.
This looks perfect to me. A little bit of time trapping on key_register and key_unregister might explain what's up. There should be one key_register and a matching key_unregister for each exported type. Since this is very hard to reproduce, could I ask you to spend a little time investigating why this seems not to be true in this case? I would hope that trapping on these two functions and watching what the arguments are might shed light on the mystery. Robert Ramey

Robert, Thanks for your response.
Sure, understand. The problem is that in release mode my application just hangs indefinitely after main() exited and there is no way of terminating it short of kill -9. Not something I can ask my users to do all the time.
In a pinch, you can tweak your copy of the library while this gets sorted out.
A bit more detail about how I set things up:
I'm serializing polymorphic objects through a shared_ptr to the base class. The object definitions are distributed over several shared libraries, all of them loaded using dlopen (on Windows 32/64Bit everything is fine, BTW). Each object has a corresponding BOOST_CLASS_EXPORT() placed in one of the cpp files each (not the headers) of the corresponding shared library. Boost serialization is linked dynamically (to ensure to have one typeinfo registry) as well, but the corresponding shared (boost) library is linked with the application, so it is loaded at application startup.
This looks perfect to me.
A little bit of time trapping on key_register and key_unregister might explain what's up.
There should be one key_register and a matching key_unregister for each exported type. Since this is very hard to reproduce, could I ask you to spend a little time investigating why this seems not to be true in this case? I would hope that trapping on these two functions and watching what the arguments are might shed light on the mystery.
Ok, here is what I got. Everything suddenly starts to work as soon as there is at least one BOOST_CLASS_EXPORT() inside a shared library which is loaded at application startup (not loaded with dlopen()). But please don't ask me why, it's just good to know. Perhaps we're dealing with some idiosyncrasies of the dlopen() library in combination with gcc symbol visibility rules. Problem solved, thanks again! Regards Hartmut

Hartmut Kaiser wrote:
Ok, here is what I got. Everything suddenly starts to work as soon as there is at least one BOOST_CLASS_EXPORT() inside a shared library which is loaded at application startup (not loaded with dlopen()).
LOL - this is the kind of thing that in a million years would not have occurred to me.
But please don't ask me why, it's just good to know. Perhaps we're dealing with some idiosyncrasies of the dlopen() library in combination with gcc symbol visibility rules.
I would guess a more likely (and perhaps fixable) cause. The serialization::singleton guarentees that and instance of an object is initialized before first usage. Perhaps something isn't being used "soon enough" when all exports are in DLLS. It has been found that in gcc compilers, static destructors are not called in reverse order of invokation of static constructors. This is the function is "is_destroyed". My guess is that there is something which should be forced to be initialiezed at application startup. looks like we'll have to wait and see what it is. Robert Ramey
Problem solved, thanks again! Regards Hartmut
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

on Thu Oct 23 2008, "Hartmut Kaiser" <hartmut.kaiser-AT-gmail.com> wrote:
There should be one key_register and a matching key_unregister for each exported type. Since this is very hard to reproduce, could I ask you to spend a little time investigating why this seems not to be true in this case? I would hope that trapping on these two functions and watching what the arguments are might shed light on the mystery.
Ok, here is what I got. Everything suddenly starts to work as soon as there is at least one BOOST_CLASS_EXPORT() inside a shared library which is loaded at application startup (not loaded with dlopen()). But please don't ask me why, it's just good to know. Perhaps we're dealing with some idiosyncrasies of the dlopen() library in combination with gcc symbol visibility rules.
Do dynamic initializations of namespace scope objects occur when a library is loaded solely through dlopen? If not, that would explain it. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
David Abrahams
-
Hartmut Kaiser
-
Robert Ramey