Hello,
I am struggling to understand a backtrace given to me by Helgrind,
because it seems to be impossible:
==16699== Helgrind, a thread error detector
==16699== Copyright (C) 2007-2015, and GNU GPL'd, by OpenWorks LLP et al.
==16699== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==16699== Command: ./testfs --noblock /lib mnt
==16699== Parent PID: 3636
[...]
==16699== Lock at 0x6520E10 was first observed
==16699== at 0x4C3010C: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x1146B1: __gthread_mutex_lock (gthr-default.h:748)
==16699== by 0x1146B1: lock (std_mutex.h:103)
==16699== by 0x1146B1: lock_guard (std_mutex.h:162)
==16699== by 0x1146B1: sfs_opendir(fuse_req*, unsigned long,
fuse_file_info*) (testfs.cpp:870)
==16699== by 0x4E5325B: do_opendir (fuse_lowlevel.c:1442)
==16699== by 0x4E54170: fuse_session_process_buf_int (fuse_lowlevel.c:2579)
==16699== by 0x4E4FE00: fuse_do_work (fuse_loop_mt.c:163)
==16699== by 0x4C32D06: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x507F493: start_thread (pthread_create.c:333)
==16699== by 0x5916ACE: clone (clone.S:97)
==16699== Address 0x6520e10 is 16 bytes inside a block of size 56 alloc'd
==16699== at 0x4C2D8CF: operator new(unsigned long, std::nothrow_t const&)
(in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x1147F0: sfs_opendir(fuse_req*, unsigned long,
fuse_file_info*) (testfs.cpp:861)
==16699== by 0x4E5325B: do_opendir (fuse_lowlevel.c:1442)
==16699== by 0x4E54170: fuse_session_process_buf_int (fuse_lowlevel.c:2579)
==16699== by 0x4E4FE00: fuse_do_work (fuse_loop_mt.c:163)
==16699== by 0x4C32D06: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x507F493: start_thread (pthread_create.c:333)
==16699== by 0x5916ACE: clone (clone.S:97)
==16699== Block was alloc'd by thread #4
==16699==
==16699== Lock at 0x654A250 was first observed
==16699== at 0x4C3010C: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x1146B1: __gthread_mutex_lock (gthr-default.h:748)
==16699== by 0x1146B1: lock (std_mutex.h:103)
==16699== by 0x1146B1: lock_guard (std_mutex.h:162)
==16699== by 0x1146B1: sfs_opendir(fuse_req*, unsigned long,
fuse_file_info*) (testfs.cpp:870)
==16699== by 0x4E5325B: do_opendir (fuse_lowlevel.c:1442)
==16699== by 0x4E54170: fuse_session_process_buf_int (fuse_lowlevel.c:2579)
==16699== by 0x4E4FE00: fuse_do_work (fuse_loop_mt.c:163)
==16699== by 0x4C32D06: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x507F493: start_thread (pthread_create.c:333)
==16699== by 0x5916ACE: clone (clone.S:97)
==16699== Address 0x654a250 is 16 bytes inside a block of size 40 alloc'd
==16699== at 0x4C2D63F: operator new(unsigned long) (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x116979: allocate (new_allocator.h:104)
==16699== by 0x116979: allocate (alloc_traits.h:436)
==16699== by 0x116979: _M_allocate_node<const std::piecewise_construct_t&,
std::tuple<const std::pair<long unsigned int, long unsigned int>&>,
std::tuple<> > (hashtable_policy.h:1947)
==16699== by 0x116979: operator[] (hashtable_policy.h:595)
==16699== by 0x116979: operator[] (unordered_map.h:904)
==16699== by 0x116979: sfs_do_lookup(fuse_req*, unsigned long, char const*,
fuse_entry_param*, bool) [clone .constprop.982] (testfs.cpp:525)
==16699== by 0x116F5D: sfs_do_readdir(fuse_req*, unsigned long, unsigned
long, long, fuse_file_info*, int) (testfs.cpp:950)
==16699== by 0x4E51789: do_readdirplus (fuse_lowlevel.c:1470)
==16699== by 0x4E54170: fuse_session_process_buf_int (fuse_lowlevel.c:2579)
==16699== by 0x4E4FE00: fuse_do_work (fuse_loop_mt.c:163)
==16699== by 0x4C32D06: ??? (in
/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==16699== by 0x507F493: start_thread (pthread_create.c:333)
==16699== by 0x5916ACE: clone (clone.S:97)
==16699== Block was alloc'd by thread #6
[...]
Note that both locks were first seen in testfs.cpp:870. However,
(according to Valgrind) the first lock was allocated in testfs.cpp:861
and the second in testfs.cpp:525.
However, the relevant code in testfs.cpp looks like this:
static void sfs_opendir(fuse_req_t req, fuse_ino_t ino, fuse_file_info *fi) {
[...]
auto d = new (nothrow) DirHandle; // === line 861 ===
if (d == nullptr) {
fuse_reply_err(req, ENOMEM);
return;
}
// Make Helgrind happy - it can't know that there's an implicit
// synchronization due to the fact that other threads cannot
// access d until we've called fuse_reply_*.
lock_guard<mutex> g {d->m}; // === line 870 ===
In other words, a lock that is first seen in line 870 cannot have been
allocated anywhere other than line 861. It is a fresh, local variable
pointing at a newly allocated buffer.
Therefore, it seems to me that the backtrace given for the allocation of
the second lock cannot possibly be correct.
Am I missing something?
Best,
-Nikolaus
--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«
_______________________________________________
Valgrind-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-users