This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libstdc++/12658] New: Thread safety problems in locale::global() and locale::locale()


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]