Boost logo

Boost Users :

Subject: [Boost-users] Valgrind's DRD tool produces false positives when used with Boost.Thread?
From: Seth Fowler (sfowler_at_[hidden])
Date: 2009-08-01 19:37:51


Hi all,

I've been trying to debug some data races in an application that uses
Boost.Thread. I tried running valgrind's DRD tool against my binary to
see if it could locate the source of the problem. It produced more
errors than I expected, so I progressively removed portions of my
application unless I was left with almost nothing. I found that even
with the most minimal program I could produce, the DRD tool still
reported errors - in fact, it even reported errors with the examples
included with the Boost distribution! I was able to reproduce this
behavior on Mac OS X 10.5.7 with Boost 1.39, and on Ubuntu 9.04 with
Boost 1.37.

Here are steps to reproduce the problem:

1. Build the sample program thread.cpp included in the Boost
distribution in libs/thread/example. For Boost 1.39, I used the
following command:

g++ -L<Boost lib directory> -lboost_thread-xgcc40-mt-1_39 thread.cpp -
o thread

2. Run it using valgrind's DRD tool:

valgrind --tool=drd --var-info=yes ./thread

On Mac OS X 10.5.7, I get the following output:

==20729== drd, a thread error detector.
==20729== Copyright (C) 2006-2009, and GNU GPL'd, by Bart Van Assche.
==20729== Using Valgrind-3.5.0.SVN and LibVEX; rerun with -h for
copyright info
==20729== Command: ./thread
==20729==
--20729-- ./thread:
--20729-- dSYM directory is missing; consider using --auto-run-
dsymutil=yes
setting alarm for 5 seconds...
==20729== Conflicting load by thread 1 at 0x00012018 size 4
==20729== at 0x58B1: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x390C: boost::thread::join() (in ./thread)
==20729== by 0x9A13: main (in ./thread)
==20729== Allocation context: Data section of ./thread
==20729== Other segment start (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x5993: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x39BC2: pthread_mutex_unlock
(drd_pthread_intercepts.c:633)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment start (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x58D2: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x39BC2: pthread_mutex_unlock
(drd_pthread_intercepts.c:633)
==20729== by 0x5988: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729==
==20729== Conflicting load by thread 1 at 0x00012014 size 4
==20729== at 0x58B4: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x390C: boost::thread::join() (in ./thread)
==20729== by 0x9A13: main (in ./thread)
==20729== Allocation context: Data section of ./thread
==20729== Other segment start (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x5993: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x39BC2: pthread_mutex_unlock
(drd_pthread_intercepts.c:633)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment start (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x58D2: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x39BC2: pthread_mutex_unlock
(drd_pthread_intercepts.c:633)
==20729== by 0x5988: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729==
==20729== Conflicting load by thread 1 at 0x00013b5c size 4
==20729== at 0x993A: boost::detail::get_once_per_thread_epoch()
(in ./thread)
==20729== by 0x58BA: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x390C: boost::thread::join() (in ./thread)
==20729== by 0x9A13: main (in ./thread)
==20729== Allocation context: Data section of ./thread
==20729== Other segment start (thread 2)
==20729== at 0x227FF0: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x58D2: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729==
==20729== Conflicting load by thread 1 at 0x00013b5c size 4
==20729== at 0x9972: boost::detail::get_once_per_thread_epoch()
(in ./thread)
==20729== by 0x58BA: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x390C: boost::thread::join() (in ./thread)
==20729== by 0x9A13: main (in ./thread)
==20729== Allocation context: Data section of ./thread
==20729== Other segment start (thread 2)
==20729== at 0x227FF0: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x58D2: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
==20729==
==20729== Conflicting load by thread 1 at 0x00397680 size 4
==20729== at 0x20038D: pthread_setspecific (in /usr/lib/
libSystem.B.dylib)
==20729== by 0x997F: boost::detail::get_once_per_thread_epoch()
(in ./thread)
==20729== by 0x58BA: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x390C: boost::thread::join() (in ./thread)
==20729== by 0x9A13: main (in ./thread)
==20729== Allocation context: Data section of /usr/lib/libSystem.B.dylib
==20729== Other segment start (thread 2)
==20729== at 0x227FF0: thread_start (in /usr/lib/libSystem.B.dylib)
==20729== Other segment end (thread 2)
==20729== at 0x396B3: pthread_mutex_lock (drd_pthread_intercepts.c:
580)
==20729== by 0x58D2: void boost::call_once<void (*)
()>(boost::once_flag&, void (*)()) (in ./thread)
==20729== by 0x30CC: thread_proxy (in ./thread)
==20729== by 0x3707B: vgDrd_thread_wrapper
(drd_pthread_intercepts.c:272)
==20729== by 0x228154: _pthread_start (in /usr/lib/libSystem.B.dylib)
==20729== by 0x228011: thread_start (in /usr/lib/libSystem.B.dylib)
alarm sounded...
==20729==
==20729== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 725
from 8)

The output on linux is similar.

Does this indicate a problem with valgrind's DRD tool, Boost.Thread,
or both? Does any workaround exist?

Thanks in advance,
- Seth Fowler


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net