This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libstdc++/12658] New: Thread safety problems in locale::global() and locale::locale()
- From: "peturr02 at ru dot is" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 17 Oct 2003 09:52:24 -0000
- Subject: [Bug libstdc++/12658] New: Thread safety problems in locale::global() and locale::locale()
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12658
Summary: Thread safety problems in locale::global() and
locale::locale()
Product: gcc
Version: 3.4
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libstdc++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: peturr02 at ru dot is
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: i686-pc-linux-gnu
GCC host triplet: i686-pc-linux-gnu
GCC target triplet: i686-pc-linux-gnu
1)
locale::global(const locale&) is defined so:
locale
locale::global(const locale& __other)
{
_S_initialize();
// XXX MT
_Impl* __old = _S_global;
__other._M_impl->_M_add_reference();
_S_global = __other._M_impl;
if (_S_global->_M_check_same_name()
&& (std::strcmp(_S_global->_M_names[0], "*") != 0))
setlocale(LC_ALL, __other.name().c_str());
// Reference count sanity check: one reference removed for the
// subsition of __other locale, one added by return-by-value. Net
// difference: zero. When the returned locale object's destrutor
// is called, then the reference count is decremented and possibly
// destroyed.
return locale(__old);
}
If two threads run locale::global() at the same time, such that:
1) thread 1 begins and executes
_Impl* __old = _S_global;
and then yields.
2) thread 2 runs locale::global() completely.
3) thread 1 resumes executions and completes.
Then the reference count of __old is decremented twice, although _S_global
only holds 1 reference. To compensate, the reference count of the locale
assigned to _S_global in thread 2 is incremented, but no reference to it
is stored so is leaked.
2)
locale::locale is defined so:
locale::locale() throw()
{
_S_initialize();
(_M_impl = _S_global)->_M_add_reference();
}
If
1) thread 1 runs locale::locale() and yields after executing
_M_impl = _S_global but before calling _M_add_reference(), and
the reference count of _S_global is 1.
2) thread 2 runs locale::global() completely and decrements the
reference count of _S_global.
3) thread 1 resumes execution and calls _M_impl->_M_add_reference()
The last reference to _S_global is removed in 2), so
_M_add_reference() in 3) is called on an object that has already been
deleted.