Opened 14 years ago
#2939 new Bugs
Possible thread-safety issue with Boost Function
Reported by: | Owned by: | Douglas Gregor | |
---|---|---|---|
Milestone: | Boost 1.39.0 | Component: | function |
Version: | Boost 1.38.0 | Severity: | Problem |
Keywords: | Cc: |
Description
Hi, I realize this might slip through the mailing lists so I am posting it here:
http://article.gmane.org/gmane.comp.lib.boost.devel/188442
I was just looking through the Boost Function source and noticed the following in assign_to:
// Note: it is extremely important that this initialization use // static initialization. Otherwise, we will have a race // condition here in multi-threaded code. See // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. static vtable_type stored_vtable = { { &manager_type::manage }, &invoker_type::invoke };
However, my copy of the C++ standard seems to say this regarding local statics in section 6.7:
The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope.
I read this to mean that an implementation may decide to initialize stored_vtable statically or the first time the block is entered. So I think that this means we cannot rely on static initialization behaviour.
If you agree, then a simple fix for this might just be:
template<typename VTable, typename Invoker, typename Manager> struct vtable_static_constructor { static VTable vtable; }; template<...> VTable vtable_static_constructor<V,I,M>::vtable = { {&Manager::manage, &Manager::invoke } }; assign_to() { ... vtable_type & stored_vtable = vtable_static_constructor<vtable_type,invoker_type,manager_type>::vtable; ... }
If not, could you please point me to where in the standard this is guaranteed to be statically initialized? It would help me decide whether or not to fix some other code that has a similar pattern, if nothing else.
Thanks in advance!