[system] local static and threading in C++03
Hello, Boost.System returns the system_category this way: BOOST_SYSTEM_DECL const error_category & system_category() { static const system_error_category system_category_const; return system_category_const; } But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently? Regards, -- Felipe Magno de Almeida
Felipe Magno de Almeida wrote
Hello,
Boost.System returns the system_category this way:
BOOST_SYSTEM_DECL const error_category & system_category() { static const system_error_category system_category_const; return system_category_const; }
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Yes sure, this is always possible zith c++0·. Do you see a problem with this implementation? Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/system-local-static-and-threading-in-C-03... Sent from the Boost - Users mailing list archive at Nabble.com.
Hello Vicente,
On Tue, Dec 25, 2012 at 6:28 PM, Vicente Botet
Felipe Magno de Almeida wrote
Hello,
[snip - source code]
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Yes sure, this is always possible zith c++0·.
Not always possible. It is only possible for non-PODs. AFAIK.
Do you see a problem with this implementation?
Since it has a race-condition, I would say I see a problem, yes. More so since it is not documented. AFAIK, the normal solution for this is to use call_once. system_category const& create_system_category() { system_category const category; return category; } void init_system_category() { create_system_category(); } once_flag init_flag = BOOST_ONCE_INIT; system_category const& get_system_category() { boost::call_once(init_flag, &init_system_category); return create_system_category(); }
Best, Vicente
Regards, -- Felipe Magno de Almeida
-- View this message in context: http://boost.2283326.n4.nabble.com/system-local-static-and-threading-in-C-03... Sent from the Boost - Users mailing list archive at Nabble.com.
Felipe Magno de Almeida wrote
Hello Vicente,
On Tue, Dec 25, 2012 at 6:28 PM, Vicente Botet <
vicente.botet@
> wrote:
Felipe Magno de Almeida wrote
Hello,
[snip - source code]
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Yes sure, this is always possible zith c++0·.
Not always possible. It is only possible for non-PODs. AFAIK.
Do you see a problem with this implementation?
Since it has a race-condition, I would say I see a problem, yes. More so since it is not documented.
Form a theoretical point of view yes. But in practice, which observable problems could induce the double construction? I would expect only one destruction, don`t you?
AFAIK, the normal solution for this is to use call_once.
system_category const& create_system_category() { system_category const category; return category; } void init_system_category() { create_system_category(); } once_flag init_flag = BOOST_ONCE_INIT;
system_category const& get_system_category() { boost::call_once(init_flag, &init_system_category); return create_system_category(); }
This approach would make both libraries interdependent. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/system-local-static-and-threading-in-C-03... Sent from the Boost - Users mailing list archive at Nabble.com.
On Thu, Dec 27, 2012 at 9:30 AM, Vicente Botet
Felipe Magno de Almeida wrote
Hello Vicente,
On Tue, Dec 25, 2012 at 6:28 PM, Vicente Botet <
vicente.botet@
> wrote:
Felipe Magno de Almeida wrote
Hello,
[snip - source code]
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Yes sure, this is always possible zith c++0·.
Not always possible. It is only possible for non-PODs. AFAIK.
Do you see a problem with this implementation?
Since it has a race-condition, I would say I see a problem, yes. More so since it is not documented.
Form a theoretical point of view yes. But in practice, which observable problems could induce the double construction? I would expect only one destruction, don`t you?
No, I wouldn't. If it is constructed twice, I would expect atexit to be called twice as well. So double destruction.
AFAIK, the normal solution for this is to use call_once.
system_category const& create_system_category() { system_category const category; return category; } void init_system_category() { create_system_category(); } once_flag init_flag = BOOST_ONCE_INIT;
system_category const& get_system_category() { boost::call_once(init_flag, &init_system_category); return create_system_category(); }
This approach would make both libraries interdependent.
I don't understand what you mean.
Best, Vicente
[snip] Regards, -- Felipe Magno de Almeida
Felipe Magno de Almeida wrote
On Thu, Dec 27, 2012 at 9:30 AM, Vicente Botet <
vicente.botet@
> wrote:
Felipe Magno de Almeida wrote
Hello Vicente,
On Tue, Dec 25, 2012 at 6:28 PM, Vicente Botet <
vicente.botet@
> wrote:
Felipe Magno de Almeida wrote
Hello,
[snip - source code]
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Yes sure, this is always possible zith c++0·.
Not always possible. It is only possible for non-PODs. AFAIK.
Do you see a problem with this implementation?
Since it has a race-condition, I would say I see a problem, yes. More so since it is not documented.
Form a theoretical point of view yes. But in practice, which observable problems could induce the double construction?
Could you answer this question?
I would expect only one destruction, don`t you?
No, I wouldn't. If it is constructed twice, I would expect atexit to be called twice as well. So double destruction.
I don`t know. Anyway, which observable problems could induce this double destruction?
AFAIK, the normal solution for this is to use call_once.
system_category const& create_system_category() { system_category const category; return category; } void init_system_category() { create_system_category(); } once_flag init_flag = BOOST_ONCE_INIT;
system_category const& get_system_category() { boost::call_once(init_flag, &init_system_category); return create_system_category(); }
This approach would make both libraries interdependent.
I don't understand what you mean.
Boost.System will depend on Boost.Thread and Boost.Thread already depends on Boost.System. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/system-local-static-and-threading-in-C-03... Sent from the Boost - Users mailing list archive at Nabble.com.
On Thu, Dec 27, 2012 at 5:42 PM, Vicente Botet
Felipe Magno de Almeida wrote
On Thu, Dec 27, 2012 at 9:30 AM, Vicente Botet <
vicente.botet@
[snip]
Form a theoretical point of view yes. But in practice, which observable problems could induce the double construction?
Could you answer this question?
I don't think I can. It is a race condition. What can happen? Anything I guess, it would depend on the implementation. I do feel very uneasy about concurrency bugs. They do bite.
I would expect only one destruction, don`t you?
No, I wouldn't. If it is constructed twice, I would expect atexit to be called twice as well. So double destruction.
I don`t know. Anyway, which observable problems could induce this double destruction?
I think double-free of allocated memory is quite possible, but I think anything is possible depending on implementation details. I rather not rely on implementation details. Also, I was expecting race conditions to be taken more seriously than to wait for bad behavior to appear. It is, afterall, a correctness issue. [snip]
This approach would make both libraries interdependent.
I don't understand what you mean.
Boost.System will depend on Boost.Thread and Boost.Thread already depends on Boost.System.
I see. I rather they be interdependent than to have race conditions. And I don't think call_once requires boost.system. So at least cyclic includes could be avoided.
Best, Vicente
Regards, -- Felipe Magno de Almeida
Le 27/12/12 21:32, Felipe Magno de Almeida a écrit :
On Thu, Dec 27, 2012 at 5:42 PM, Vicente Botet
wrote: Felipe Magno de Almeida wrote
On Thu, Dec 27, 2012 at 9:30 AM, Vicente Botet < vicente.botet@ [snip]
Form a theoretical point of view yes. But in practice, which observable problems could induce the double construction? Could you answer this question? I don't think I can. It is a race condition. What can happen? Anything I guess, it would depend on the implementation. I do feel very uneasy about concurrency bugs. They do bite.
I would expect only one destruction, don`t you? No, I wouldn't. If it is constructed twice, I would expect atexit to be called twice as well. So double destruction. I don`t know. Anyway, which observable problems could induce this double destruction? I think double-free of allocated memory is quite possible, but I think anything is possible depending on implementation details. I rather not rely on implementation details. I don't see any allocation there. Boost has a lot of code that depends on compiler implementation details. Also, I was expecting race conditions to be taken more seriously than to wait for bad behavior to appear. It is, afterall, a correctness issue. You are right. the issue should be taken in account.
Does the following schema extracted from Boost.Units solve the issue or it works only for POD types? namespace detail { template<bool> struct xalloc_key_holder { static int value; static bool initialized; }; template<bool b> int xalloc_key_holder<b>::value = 0; template<bool b> bool xalloc_key_holder<b>::initialized = 0; struct xalloc_key_initializer_t { xalloc_key_initializer_t() { if (!xalloc_key_holder<true>::initialized) { xalloc_key_holder<true>::value = std::ios_base::xalloc(); xalloc_key_holder<true>::initialized = true; } } }; namespace /**/ { xalloc_key_initializer_t xalloc_key_initializer; } // namespace } // namespace detail /// returns flags controlling output. inline long get_flags(std::ios_base& ios, long mask) { return(ios.iword(detail::xalloc_key_holder<true>::value) & mask); }
[snip]
This approach would make both libraries interdependent. I don't understand what you mean. Boost.System will depend on Boost.Thread and Boost.Thread already depends on Boost.System. I see. I rather they be interdependent than to have race conditions. And I don't think call_once requires boost.system. So at least cyclic includes could be avoided.
Yes, but this will mean to have two Boost.Thread libraries boost_thread (with call_once) and boost_futures (which depend on Boost.System). I'm not against this but this will mean a new breaking change. Best, Vicente
On Sun, Dec 30, 2012 at 3:39 PM, Vicente J. Botet Escriba
Le 27/12/12 21:32, Felipe Magno de Almeida a écrit :
[snip]
I think double-free of allocated memory is quite possible, but I think anything is possible depending on implementation details. I rather not rely on implementation details.
I don't see any allocation there. Boost has a lot of code that depends on compiler implementation details.
I might be wrong about allocation and deallocation on most implementations. I'm not against using implementation details, but they should be explicit, and ifdef'ed with a default implementation for other compilers.
Also, I was expecting race conditions to be taken more seriously than to wait for bad behavior to appear. It is, afterall, a correctness issue.
You are right. the issue should be taken in account.
Does the following schema extracted from Boost.Units solve the issue or it works only for POD types?
namespace detail {
template<bool> struct xalloc_key_holder { static int value; static bool initialized; };
template<bool b> int xalloc_key_holder<b>::value = 0;
template<bool b> bool xalloc_key_holder<b>::initialized = 0;
struct xalloc_key_initializer_t { xalloc_key_initializer_t() { if (!xalloc_key_holder<true>::initialized) { xalloc_key_holder<true>::value = std::ios_base::xalloc(); xalloc_key_holder<true>::initialized = true; } } };
namespace /**/ {
xalloc_key_initializer_t xalloc_key_initializer;
} // namespace
} // namespace detail
/// returns flags controlling output. inline long get_flags(std::ios_base& ios, long mask) { return(ios.iword(detail::xalloc_key_holder<true>::value) & mask);
}
I might not be knowledgeable enough to comment, but this seem a very strange hack for the initialization order fiasco. [snip]
Boost.System will depend on Boost.Thread and Boost.Thread already depends on Boost.System.
I see. I rather they be interdependent than to have race conditions. And I don't think call_once requires boost.system. So at least cyclic includes could be avoided.
Yes, but this will mean to have two Boost.Thread libraries boost_thread (with call_once) and boost_futures (which depend on Boost.System). I'm not against this but this will mean a new breaking change.
If call_once were made header-only, there wouldn't be any breakage. IIUC.
Best, Vicente
Regards, -- Felipe Magno de Almeida
On Sun, Dec 30, 2012 at 3:39 PM, Vicente J. Botet Escriba
wrote: Le 27/12/12 21:32, Felipe Magno de Almeida a écrit : [snip]
Also, I was expecting race conditions to be taken more seriously than to wait for bad behavior to appear. It is, afterall, a correctness issue. You are right. the issue should be taken in account.
Does the following schema extracted from Boost.Units solve the issue or it works only for POD types?
namespace detail {
template<bool> struct xalloc_key_holder { static int value; static bool initialized; };
template<bool b> int xalloc_key_holder<b>::value = 0;
template<bool b> bool xalloc_key_holder<b>::initialized = 0;
struct xalloc_key_initializer_t { xalloc_key_initializer_t() { if (!xalloc_key_holder<true>::initialized) { xalloc_key_holder<true>::value = std::ios_base::xalloc(); xalloc_key_holder<true>::initialized = true; } } };
namespace /**/ {
xalloc_key_initializer_t xalloc_key_initializer;
} // namespace
} // namespace detail
/// returns flags controlling output. inline long get_flags(std::ios_base& ios, long mask) { return(ios.iword(detail::xalloc_key_holder<true>::value) & mask);
} I might not be knowledgeable enough to comment, but this seem a very strange hack for the initialization order fiasco. I don't know if it is a hack, but is been used in Boost in a lot of
Le 31/12/12 00:15, Felipe Magno de Almeida a écrit : libraries.
[snip]
Boost.System will depend on Boost.Thread and Boost.Thread already depends on Boost.System. I see. I rather they be interdependent than to have race conditions. And I don't think call_once requires boost.system. So at least cyclic includes could be avoided.
Yes, but this will mean to have two Boost.Thread libraries boost_thread (with call_once) and boost_futures (which depend on Boost.System). I'm not against this but this will mean a new breaking change. If call_once were made header-only, there wouldn't be any breakage. IIUC.
I let you and Beman (Boost.System author) to continue this discussion. Please, create a Trac ticket for Boost.thread if some modifications are needed. Best, Vicente
On Mon, Dec 24, 2012 at 8:40 AM, Felipe Magno de Almeida < felipe.m.almeida@gmail.com> wrote:
Hello,
Boost.System returns the system_category this way:
BOOST_SYSTEM_DECL const error_category & system_category() { static const system_error_category system_category_const; return system_category_const; }
But couldn't this make double construction/double free in C++03 systems if system_category is ran concurrently?
Regards, -- Felipe Magno de Almeida
If this is in a cpp file and not a header, then just move system_category_const outside the function. Tony
participants (4)
-
Felipe Magno de Almeida
-
Gottlob Frege
-
Vicente Botet
-
Vicente J. Botet Escriba