Boost logo

Boost :

From: Robert Ramey (ramey_at_[hidden])
Date: 2005-08-19 02:29:24


>>> Besides, I don't understand how you
>>> can "inhibit loading of DLLS". Say, one thread has created an
>>> archive and does something with it. Some other thread tries to open
>>> DLL. What should happen? Should that other thread get "sorry, some
>>> archives are open" error? And what
>>> will it do?

I havn't considered it in detail but its easy to consider using a semaphore
(even though I'm sure there are better solutions). Semaphore is incremented
each time an archive is opened. DLL Loading/Unloading code blocks until
reaches zero. This could be implemented without touching the serialization
library at all:

a) derive text_archive_with_semaphore (dtaws) from text_archive_impl
b) in constructor of dtaws increment global semaphore
c) in destructuctor of dtaws-decrement global semaphore
d) DLL loader/unloader waits on same semaphore that dtaws uses.

Thus - this very rare case whereby the set of types which implement
serialization is changing during the course of the program is easily handled
without complicating the serialization library.

> Okay, but then assume the following scenario:
>
> 1. A program creates an archive to read from network connection.
> Network connection is never to be closed.
>
> 2. A command arrives via connection that requires loading a plugin.
>
> 3. The plugin has BOOST_CLASS_EXPORT, so attempt to load it crashes.
> We have two possibilities:
>
> 3a. Since the exception happens when you modified serialization
> tables, and that happens in static initializer, you cannot catch the
> exception anywhere in the plugin code. Since the plugin (on Unix), is
> opened with C function dlopen, it's not clear if the exception will
> propagated across that C function. So, the whole application might
> crash.

> 3b. Assume we checked if archives are opened before calling dlopen.
> Actually, we cannot, because we don't know, generally speaking, if the
> plugin uses BOOST_CLASS_EXPORT or not. But assume we somehow know
> this and figured that we can't load the plugin. Now:
>
> - we can't close the network connection, because it waits for
> further commands
> - we can't load plugin because some archive is opened, so we can
> do the previous command we've received

I'm not sure I get all this. In general the recieving machine would have to
have the code for doing the loading installed before the archive is opened.
It would seem to me you would need to break this in to two transations. One
communicate which DLL might be necessary - passing the DLL which contains
the right code. Then close the archve, load all desired DLLS and construct
a new archive for the "real" data which might be serialized from one of the
previous DLLS.

> Neither alternative looks particularly attractive to me.
>
>> There's another aspect here. The code for serialization presumes
>> that the global tables are static during the lifetime of the
>> archive. For example, as a particular item is serialized, its class
>> identifier is saved in an archive specific table. Thus the save
>> code used the object identifier to invoke the save method for the
>> specific class. Same goes for the load side. Now, if the global
>> table changes while an archive is open, all bets are off
>> because the save/load code may not be around anymore. So.
>>
>> a) global tables can't be changed while an archive is open an still
>> expect the system to function.

> This is over-generalisation. Clearly, new BOOST_CLASS_EXPORT
> statements won't break anything.

The will if they are included in a DLL that is unload in the middle of the
saving/loading of
an archive which contains classes of the indicated type.

>> b) thus DLLS should be loaded/unloaded only when there are no
>> archives open.

> It's only disallowed to save/load objects that come from DLL and
> registered in global id table for which the corresponding DLL is
> unloaded. What this means is that ids should be removed from global
> table on DLL unload -- I think this can be done by implementing a
> destructor in the same helper classes that registers id in its
> constructor.

This is already implemented. Its not a problem - the problem is doing in
the middle of loading/saving an archive.

>> c) respecting this rule is the responsability of the calling
>> program.
>
> As I've shown above, it's not always possible to respect this rule.

Based on my semaphore example above - I disagree.

>> While we're at it, I would also like to consider enforcing a rule
>> that there can be at most one instance of serialization code for a
>> specific type existing at one time.
>
> What do you mean? If there are two DLL defining the same function but
> with different bodies, that's ODR violation. If they define the same
> function with the same body, that's no problem.

Exactly. But since the code resides in different DLLS which are not visible
at compiler time, the ODR violaton cannot be detected by either the compiler
or the linker. Actually I'm not sure what happens when one dynamically
loads two different DLLS which contain the same function signatures. I
suppose its implementation dependent. Either its prohibited by the part of
the OS that loads DLLS or it isn't. I very much doubt that it check to see
if the code is the same and permits if and only if the code is identical.

To summarize

a) The only case of a conflict between serialization an mult-threading
arises only with very unusual case of dynamically loading/unloading DLLS
which contain serialization code.

b) In the case where one feels the need to do this, it can be best addressed
outside the serialization library itself.

Robert Ramey


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk