stdcxx-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Stefan Teleman (Issue Comment Edited) (JIRA)" <j...@apache.org>
Subject [jira] [Issue Comment Edited] (STDCXX-1056) std::moneypunct and std::numpunct implementations are not thread-safe
Date Mon, 06 Feb 2012 22:02:59 GMT

    [ https://issues.apache.org/jira/browse/STDCXX-1056?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13201653#comment-13201653
] 

Stefan Teleman edited comment on STDCXX-1056 at 2/6/12 10:02 PM:
-----------------------------------------------------------------

I understand the need for writing small and efficient methods, but I don't agree that the
problem reported in STDCXX-839 relates to the test running for too long. The fact that the
test program doesn't terminate or abends with SIGHUP is a symptom of undefined run-time behavior.

{noformat}
[steleman@darthvader][/src/steleman/programming/stdcxx-ss122/stdcxx-4.2.1/build/tests][02/06/2012
16:49:50][1512]>> /usr/bin/time -p ./22.locale.numpunct.mt --nthreads=4 --nloops=100
>& t.out
[steleman@darthvader][/src/steleman/programming/stdcxx-ss122/stdcxx-4.2.1/build/tests][02/06/2012
16:50:13][1513]>> tail -17 t.out

# INFO (S1) (4 lines):
# TEXT: creating a thread pool with 4 threads
# CLAUSE: lib.locale.numpunct
# LINE: 548

# +-----------------------+----------+----------+----------+
# | DIAGNOSTIC            |  ACTIVE  |   TOTAL  | INACTIVE |
# +-----------------------+----------+----------+----------+
# | (S1) INFO             |       11 |       11 |       0% |
# | (S2) NOTE             |        1 |        1 |       0% |
# | (S8) ERROR            |        0 |        3 |     100% |
# | (S9) FATAL            |        0 |        1 |     100% |
# +-----------------------+----------+----------+----------+
real 4.95
user 1.07
sys 0.22
{noformat}

This test case (and the corresponding 22.locale.moneypunct.mt) consistently exhibit run-time
crashes or insane behavior (CPU being pinned at 99% forever) without the serialization fix.

The interesting part is where this race condition actually happens: it's in include/loc/_num_put.cc:

{code title=_num_put.cc|borderStyle=solid}

template <class _CharT, class _OutputIter /* = ostreambuf_iterator<_CharT> */>
_TYPENAME num_put<_CharT, _OutputIter>::iter_type
num_put<_CharT, _OutputIter>::
_C_put (iter_type __it, ios_base &__flags, char_type __fill, int __type,
        const void *__pval) const
{
    const numpunct<char_type> &__np =
        _RWSTD_USE_FACET (numpunct<char_type>, __flags.getloc ());

    char __buf [_RWSTD_DBL_MAX_10_EXP];

    // will grow as necessary and may need to be deleted
    char *__pbuf = __buf;

    const string            __grouping = __np.grouping (); // <----- !!
    const char* const       __grp      = __grouping.c_str (); // <----- !!
    const _RWSTD_STREAMSIZE __prec     = __flags.precision ();

{code}



                
      was (Author: steleman):
    I understand the need for writing small and efficient methods, but I don't agree that
the problem reported in STDCXX-839 relates to the test running for too long. The fact that
the test program doesn't terminate or abends with SIGHUP is a symptom of undefined run-time
behavior.

{noformat}
[steleman@darthvader][/src/steleman/programming/stdcxx-ss122/stdcxx-4.2.1/build/tests][02/06/2012
16:49:50][1512]>> /usr/bin/time -p ./22.locale.numpunct.mt --nthreads=4 --nloops=100
>& t.out
[steleman@darthvader][/src/steleman/programming/stdcxx-ss122/stdcxx-4.2.1/build/tests][02/06/2012
16:50:13][1513]>> tail -17 t.out

# INFO (S1) (4 lines):
# TEXT: creating a thread pool with 4 threads
# CLAUSE: lib.locale.numpunct
# LINE: 548

# +-----------------------+----------+----------+----------+
# | DIAGNOSTIC            |  ACTIVE  |   TOTAL  | INACTIVE |
# +-----------------------+----------+----------+----------+
# | (S1) INFO             |       11 |       11 |       0% |
# | (S2) NOTE             |        1 |        1 |       0% |
# | (S8) ERROR            |        0 |        3 |     100% |
# | (S9) FATAL            |        0 |        1 |     100% |
# +-----------------------+----------+----------+----------+
real 4.95
user 1.07
sys 0.22
{noformat}

This test case (and the corresponding 22.locale.moneypunct.mt) consistently exhibit run-time
crashes or insane behavior (CPU being pinned at 99% forever) without the serialization fix.

The interesting part is where this race condition actually happens: it's in include/loc/_num_put.cc:

{code title=_num_put.cc|borderStyle=solid}

template <class _CharT, class _OutputIter /* = ostreambuf_iterator<_CharT> */>
_TYPENAME num_put<_CharT, _OutputIter>::iter_type
num_put<_CharT, _OutputIter>::
_C_put (iter_type __it, ios_base &__flags, char_type __fill, int __type,
        const void *__pval) const
{
    const numpunct<char_type> &__np =
        _RWSTD_USE_FACET (numpunct<char_type>, __flags.getloc ());

    char __buf [_RWSTD_DBL_MAX_10_EXP];

    // will grow as necessary and may need to be deleted
    char *__pbuf = __buf;

    const string            __grouping = __np.grouping (); // <----- !!
    const char* const       __grp      = __grouping.c_str (); // <----- !!
    const _RWSTD_STREAMSIZE __prec     = __flags.precision ();
// [ ... ]
{code}


                  
> std::moneypunct and std::numpunct implementations are not thread-safe
> ---------------------------------------------------------------------
>
>                 Key: STDCXX-1056
>                 URL: https://issues.apache.org/jira/browse/STDCXX-1056
>             Project: C++ Standard Library
>          Issue Type: Bug
>          Components: 22. Localization
>    Affects Versions: 4.2.1, 4.2.x, 4.3.x, 5.0.0
>         Environment: Solaris 10 and 11, RedHat and OpenSuSE Linux, Sun C++ Compilers
12.1, 12.2, 12.3
> Issue is independent of platform and/or compiler.
>            Reporter: Stefan Teleman
>              Labels: thread-safety
>             Fix For: 4.2.x, 4.3.x, 5.0.0
>
>         Attachments: stdcxx-1056.patch
>
>
> several member functions in std::moneypunct<> and std::numpunct<> return
> a std::string by value (as required by the Standard). The implication of return-by-value
> being that the caller "owns" the returned object.
> In the stdcxx implementation, the std::basic_string copy constructor uses a shared
> underlying buffer implementation. This shared buffer creates the first problem for
> these classes: although the std::string object returned by value *appears* to be owned
> by the caller, it is, in fact, not.
> In a mult-threaded environment, this underlying shared buffer can be subsequently modified
by a different thread than the one who made the initial call. Furthermore, two or more different
threads can access the same shared buffer at the same time, and modify it, resulting in undefined
run-time behavior.
> The cure for this defect has two parts:
> 1. the member functions in question must truly return a copy by avoiding a call to the
copy constructor, and using a constructor which creates a deep copy of the std::string.
> 2. access to these member functions must be serialized, in order to guarantee atomicity
> of the creation of the std::string being returned by value.
> Patch for 4.2.1 to follow.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Mime
View raw message