|
From: Konstantin S. <kon...@gm...> - 2010-07-14 12:29:28
|
FYI:
I've constructed a test case which produces a false report with all
three tools.
The test case uses shared_ptr from the soon-to-become C++ standard
(I've built it with the fresh gcc trunk).
With the annotations which we are discussing with libstdc++ folks
these reports should be gone.
--kcc
% cat shared_ptr_test.cc
//#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(a) ANNOTATE_HAPPENS_BEFORE(a)
//#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(a) ANNOTATE_HAPPENS_AFTER(a)
//#include "dynamic_annotations.h"
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <memory>
using namespace std;
class Foo {
public:
Foo() : a_(777) { }
~Foo() {
a_ = 0xDEAD;
}
void Check() {
assert(a_ == 777);
}
private:
int a_;
};
shared_ptr<Foo> *s;
pthread_mutex_t mu;
pthread_cond_t cv;
int done = 0;
void *Thread(void*) {
shared_ptr<Foo> x(*s);
pthread_mutex_lock(&mu);
done++;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&mu);
x->Check();
// x is destructed
}
const int kNThreads = 3;
int main() {
s = new shared_ptr<Foo>(new Foo);
pthread_t t[kNThreads];
pthread_mutex_init(&mu, 0);
pthread_cond_init(&cv, 0);
// start threads.
for (int i = 0; i < kNThreads; i++) {
pthread_create(&t[i], 0, Thread, 0);
}
// wait for threads to copy 's', but don't wait for threads to exit.
pthread_mutex_lock(&mu);
while (done != kNThreads)
pthread_cond_wait(&cv, &mu);
pthread_mutex_unlock(&mu);
delete s;
}
% g++ -g -std=c++0x -pthread shared_ptr_test.cc && echo
-----Helgrind---------; ~/valgrind/trunk/inst/bin/valgrind
--tool=helgrind ./a.out && echo --------------DRD----------- &&
~/valgrind/trunk/inst/bin/valgrind --tool=drd ./a.out
-----Helgrind---------
==7788== Helgrind, a thread error detector
==7788== Copyright (C) 2007-2009, and GNU GPL'd, by OpenWorks LLP et al.
==7788== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==7788== Command: ./a.out
==7788==
==7788== Thread #1 is the program's root thread
==7788==
==7788== Thread #4 was created
==7788== at 0x58E06BE: clone (clone.S:77)
==7788== by 0x55E4172: pthread_create@@GLIBC_2.2.5 (createthread.c:75)
==7788== by 0x4C2C210: pthread_create_WRK (hg_intercepts.c:241)
==7788== by 0x4C2C2B9: pthread_create@* (hg_intercepts.c:268)
==7788== by 0x400E28: main (shared_ptr_test.cc:52)
==7788==
==7788== Possible data race during write of size 4 at 0x5b7d040 by thread #1
==7788== at 0x400ECE: Foo::~Foo() (shared_ptr_test.cc:16)
==7788== by 0x4013B7: std::_Sp_counted_ptr<Foo*,
(__gnu_cxx::_Lock_policy)2>::_M_dispose() (in /tmp/z/a.out)
==7788== by 0x401047:
std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release()
(boost_sp_counted_base.h:146)
==7788== by 0x400F8E:
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count()
(shared_ptr_base.h:353)
==7788== by 0x400F25: std::__shared_ptr<Foo,
(__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:553)
==7788== by 0x400F3F: std::shared_ptr<Foo>::~shared_ptr() (shared_ptr.h:91)
==7788== by 0x400E80: main (shared_ptr_test.cc:59)
==7788== This conflicts with a previous read of size 4 by thread #4
==7788== at 0x400EE6: Foo::Check() (shared_ptr_test.cc:19)
==7788== by 0x400D89: Thread(void*) (shared_ptr_test.cc:39)
==7788== by 0x4C2C342: mythread_wrapper (hg_intercepts.c:213)
==7788== by 0x55E39C9: start_thread (pthread_create.c:300)
==7788== by 0x58E06FC: clone (clone.S:112)
==7788== Address 0x5b7d040 is 0 bytes inside a block of size 4 alloc'd
==7788== at 0x4C27ED5: operator new(unsigned long) (vg_replace_malloc.c:261)
==7788== by 0x400DAC: main (shared_ptr_test.cc:46)
==7788==
==7788==
==7788== For counts of detected and suppressed errors, rerun with: -v
==7788== Use --history-level=approx or =none to gain increased speed, at
==7788== the cost of reduced accuracy of conflicting-access information
==7788== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 24 from 15)
--------------DRD-----------
==7792== drd, a thread error detector
==7792== Copyright (C) 2006-2009, and GNU GPL'd, by Bart Van Assche.
==7792== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==7792== Command: ./a.out
==7792==
==7792== Conflicting store by thread 1 at 0x05b86030 size 4
==7792== at 0x400ECE: Foo::~Foo() (shared_ptr_test.cc:16)
==7792== by 0x4013B7: std::_Sp_counted_ptr<Foo*,
(__gnu_cxx::_Lock_policy)2>::_M_dispose() (in /tmp/z/a.out)
==7792== by 0x401047:
std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release()
(boost_sp_counted_base.h:146)
==7792== by 0x400F8E:
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count()
(shared_ptr_base.h:353)
==7792== by 0x400F25: std::__shared_ptr<Foo,
(__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:553)
==7792== by 0x400F3F: std::shared_ptr<Foo>::~shared_ptr() (shared_ptr.h:91)
==7792== by 0x400E80: main (shared_ptr_test.cc:59)
==7792== Address 0x5b86030 is at offset 0 from 0x5b86030. Allocation context:
==7792== at 0x4C29A05: operator new(unsigned long) (vg_replace_malloc.c:261)
==7792== by 0x400DAC: main (shared_ptr_test.cc:46)
==7792== Other segment start (thread 2)
==7792== (thread finished, call stack no longer available)
==7792== Other segment end (thread 2)
==7792== (thread finished, call stack no longer available)
==7792== Other segment start (thread 3)
==7792== (thread finished, call stack no longer available)
==7792== Other segment end (thread 3)
==7792== (thread finished, call stack no longer available)
==7792== Other segment start (thread 4)
==7792== at 0x4C2BD19: pthread_mutex_unlock (drd_pthread_intercepts.c:633)
==7792== by 0x400D75: Thread(void*) (shared_ptr_test.cc:37)
==7792== by 0x4C344C4: vgDrd_thread_wrapper (drd_pthread_intercepts.c:272)
==7792== by 0x55EC9C9: start_thread (pthread_create.c:300)
==7792== by 0x58E96FC: clone (clone.S:112)
==7792== Other segment end (thread 4)
==7792== at 0x58E5AE7: madvise (syscall-template.S:82)
==7792==
==7792==
==7792== For counts of detected and suppressed errors, rerun with: -v
==7792== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 16 from 15)
On Fri, Jul 9, 2010 at 3:48 PM, Konstantin Serebryany
<kon...@gm...> wrote:
> Sent a message to libstdc++ folks:
> http://gcc.gnu.org/ml/libstdc++/2010-07/msg00029.html
>
> --kcc
>
> On Thu, Jul 8, 2010 at 7:08 PM, Bart Van Assche <bva...@ac...> wrote:
>> On Thu, Jul 8, 2010 at 12:49 PM, Konstantin Serebryany
>> <kon...@gm...> wrote:
>>> I changed the code which I want to suggest to libstdc++:
>>> http://code.google.com/p/data-race-test/wiki/AtomicReferenceCounting#Proposal_to_libstdc++_developers
>>> This will allow to use any kind of annotations (including Intel
>>> Parallel Inspector's itt_notify_sync_releasing /
>>> itt_notify_sync_acquired).
>>> Please have another look.
>>
>> A few minor comments: in the text cited below, please add the word
>> "otherwise" at the beginning of the second line, replace "other" by
>> "else" and "reference counter" by "reference counters".
>>
>> // Do not use this function for anything other than decrementing
>> reference counter --
>> // this will confuse race detectors and will make them more
>> conservative and slow.
>>
>> Bart.
>>
>
|