On Tue, Apr 6, 2010 at 3:30 AM, Bart Van Assche <[email protected]> wrote:
> On Tue, Apr 6, 2010 at 12:25 PM, Konstantin Serebryany
> <[email protected]> wrote:
>>
>>
>> On Tue, Apr 6, 2010 at 2:17 PM, Bart Van Assche <[email protected]> wrote:
>>>
>>> On Tue, Apr 6, 2010 at 7:53 AM, Jorge Moraleda <[email protected]>
>>> wrote:
>>> >
>>> > Dear all,
>>> >
>>> > When I compile the following program with:
>>> > $ g++ -g -pthread threads.cpp
>>> >
>>> > // begin program /////////////////////////////////////////////
>>> > // file: threads.cpp
>>> > #include <pthread.h>
>>> > #include <iostream>
>>> > #include <sstream>
>>> >
>>> > void *threadEntry(void *threadid)
>>> > {
>>> >   long tid;
>>> >   tid = (long)threadid;
>>> >         for (int i = 0; i<5; i++) {
>>> >                   std::stringstream myStream;
>>> >                         myStream << "this thread is " << tid;
>>> >                         std::string myString(myStream.str());
>>> >                   pthread_yield();
>>> >         }
>>> >         pthread_exit(NULL);
>>> > }
>>> >
>>> > int main (int argc, char *argv[])
>>> > {
>>> >   pthread_t threads[2];
>>> >   int rc;
>>> >   long t;
>>> >   for(t=0; t<2; t++) {
>>> >      rc = pthread_create(&threads[t], NULL, threadEntry, (void *)t);
>>> >   }
>>> >   pthread_exit(NULL);
>>> > }
>>> > // end program /////////////////////////////////////////////
>>> >
>>> > and run drd on it with:
>>> > $ valgrind --tool=drd ./a.out
>>> >
>>> > I get the following output:
>>> >
>>> > ==16240== drd, a thread error detector
>>> > ==16240== Copyright (C) 2006-2009, and GNU GPL'd, by Bart Van Assche.
>>> > ==16240== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for
>>> > copyright info
>>> > ==16240== Command: ./a.out
>>> > ==16240==
>>> > ==16240== Thread 3:
>>> > ==16240== Conflicting load by thread 3 at 0x05132e98 size 1
>>> > ==16240==    at 0x4ED44C8: std::ostream&
>>> > std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x400C48: threadEntry(void*) (threads.cpp:12)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240== Allocation context: BSS section of
>>> > /usr/lib/libstdc++.so.6.0.13
>>> > ==16240== Other segment start (thread 2)
>>> > ==16240==    at 0x4C29F2F: pthread_mutex_unlock
>>> > (drd_pthread_intercepts.c:633)
>>> > ==16240==    by 0x4EA387E: std::locale::locale() (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4E9FE5F: std::ios_base::_M_init() (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4EB4768: std::basic_ios<char, std::char_traits<char>
>>> > >::init(std::basic_streambuf<char, std::char_traits<char> >*) (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4ED7DEA: std::basic_stringstream<char,
>>> > std::char_traits<char>, std::allocator<char>
>>> > >::basic_stringstream(std::_Ios_Openmode) (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x400C21: threadEntry(void*) (threads.cpp:11)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240== Other segment end (thread 2)
>>> > ==16240==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
>>> > ==16240==    by 0x400C63: threadEntry(void*) (threads.cpp:14)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240==
>>> > ==16240== Conflicting load by thread 3 at 0x05132eb9 size 1
>>> > ==16240==    at 0x4ED44D3: std::ostream&
>>> > std::ostream::_M_insert<long>(long) (in /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x400C48: threadEntry(void*) (threads.cpp:12)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240== Allocation context: BSS section of
>>> > /usr/lib/libstdc++.so.6.0.13
>>> > ==16240== Other segment start (thread 2)
>>> > ==16240==    at 0x4C29F2F: pthread_mutex_unlock
>>> > (drd_pthread_intercepts.c:633)
>>> > ==16240==    by 0x4EA387E: std::locale::locale() (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4E9FE5F: std::ios_base::_M_init() (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4EB4768: std::basic_ios<char, std::char_traits<char>
>>> > >::init(std::basic_streambuf<char, std::char_traits<char> >*) (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x4ED7DEA: std::basic_stringstream<char,
>>> > std::char_traits<char>, std::allocator<char>
>>> > >::basic_stringstream(std::_Ios_Openmode) (in
>>> > /usr/lib/libstdc++.so.6.0.13)
>>> > ==16240==    by 0x400C21: threadEntry(void*) (threads.cpp:11)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240== Other segment end (thread 2)
>>> > ==16240==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
>>> > ==16240==    by 0x400C63: threadEntry(void*) (threads.cpp:14)
>>> > ==16240==    by 0x4C32870: vgDrd_thread_wrapper
>>> > (drd_pthread_intercepts.c:272)
>>> > ==16240==    by 0x55E8A03: start_thread (pthread_create.c:300)
>>> > ==16240==    by 0x58DD80C: clone (clone.S:112)
>>> > ==16240==
>>> > ==16240==
>>> > ==16240== For counts of detected and suppressed errors, rerun with: -v
>>> > ==16240== ERROR SUMMARY: 6 errors from 2 contexts (suppressed: 208 from
>>> > 140)
>>> >
>>> > My question is: Are the errors reported real multi threading errors?
>>> > If not, how can I tell drd to suppress them? (In my real world program,
>>> > I
>>> > have thousands of errors in hundreds of contexts, and I am trying to
>>> > find the real ones.)
>>> > If yes, can you help me understand what is wrong? Both threads only
>>> > use local variables. I have been reading about the global object
>>> > "locale" used by streams for localization, but I have read that it is
>>> > protected by a global mutex.
>>>
>>> Hello Jorge,
>>>
>>> Unfortunately not all libraries have been designed with data-race
>>> detection tools in mind. Several libraries contain code that triggers
>>> benign data races. Examples are the I/O code in libstdc++ and in libc.
>>>
>>> You can either create a suppression pattern to suppress the above
>>> races, or even simpler, add the following code in main() before thread
>>> creation starts:
>>>
>>>  std::ostringstream dummy;
>>>  dummy << 0;
>>>
>>> The above code will make sure that locale initialization, which is
>>> triggered by sending an number to an I/O stream, will happen before
>>> any threads are created and hence no races will be reported anymore on
>>> locale initialization.
>>
>> This will not hide the race on _ZNSs4_Rep20_S_empty_rep_storageE.
>> And suppressing errors in string guts may hide real races.
>
> The above indeed won't hide races on
> _ZNSs4_Rep20_S_empty_rep_storageE. But I've never claimed that the
> above code would hide these races. And Jorge didn't report any such
> races in his original e-mail. So your reply seems off-topic to me.
>
> Bart.
>

Dear Bart and Konstantin,

Thank you very much for your comments. The trick of pre-initializing
the locale object solved a few of my errors, but I still have tons
related to strings and streams. This is another minimal test case:

#include <pthread.h>
#include <string>
#include <sstream>

void *threadEntry(void *threadid)
{
   long tid;
   tid = (long)threadid;
         std::string myString;
         for (int i = 0; i<5; i++) {
                 myString.clear();
                 pthread_yield();
         }
         pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[2];
   int rc;
   long t;

         std::ostringstream dummy;
         dummy << 0;
         for(t=0; t<2; t++) {
                 rc = pthread_create(&threads[t], NULL, threadEntry, (void *)t);
         }
         pthread_exit(NULL);
}

==19065== drd, a thread error detector
==19065== Copyright (C) 2006-2009, and GNU GPL'd, by Bart Van Assche.
==19065== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for
copyright info
==19065== Command: ./a.out
==19065==
==19065== Thread 3:
==19065== Conflicting load by thread 3 at 0x05134160 size 8
==19065==    at 0x4EDF1D7: std::string::clear() (in
/usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065== Conflicting load by thread 3 at 0x05134160 size 8
==19065==    at 0x4EDE907: std::string::_M_mutate(unsigned long,
unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065== Conflicting load by thread 3 at 0x05134170 size 4
==19065==    at 0x4EDE9B0: std::string::_M_mutate(unsigned long,
unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065== Conflicting store by thread 3 at 0x05134170 size 4
==19065==    at 0x4EDE97D: std::string::_M_mutate(unsigned long,
unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065== Conflicting store by thread 3 at 0x05134160 size 8
==19065==    at 0x4EDE984: std::string::_M_mutate(unsigned long,
unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065== Conflicting store by thread 3 at 0x05134178 size 1
==19065==    at 0x4EDE987: std::string::_M_mutate(unsigned long,
unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6.0.13)
==19065==    by 0x400A5B: threadEntry(void*) (threads.cpp:12)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065== Allocation context: BSS section of /usr/lib/libstdc++.so.6.0.13
==19065== Other segment start (thread 2)
==19065==    at 0x58DD7D1: clone (clone.S:84)
==19065==    by 0x55E893F: ??? (allocatestack.c:743)
==19065==    by 0x676D90F: ???
==19065== Other segment end (thread 2)
==19065==    at 0x58ACEB7: sched_yield (in /lib/libc-2.10.1.so)
==19065==    by 0x400A60: threadEntry(void*) (threads.cpp:13)
==19065==    by 0x4C32870: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==19065==    by 0x55E8A03: start_thread (pthread_create.c:300)
==19065==    by 0x58DD80C: clone (clone.S:112)
==19065==
==19065==
==19065== For counts of detected and suppressed errors, rerun with: -v
==19065== ERROR SUMMARY: 54 errors from 6 contexts (suppressed: 205 from 142)

Are all the race conditions in  I/O code in libstdc++ bening?

If so, are there more things that I should initialize in my app before
I start creating threads and/or should I be looking into creating
suppression patterns for drd? Has anyone created them before? Why are
they not enabled by default in drd?

If not... What should I be reading,doing? Thank you in advance.

Jorge

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Valgrind-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to