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
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to