7

Using Windows CRITICAL_SECTION, I can see the thread that locked it by expanding the variable:

enter image description here

However, I can't seem to do the same with std::mutex, and get a lot of useless values instead:

enter image description here

Is there a way around it that doesn't require modifying my code?

riv
  • 6,846
  • 2
  • 34
  • 63
  • 2
    try casting the value to `_Mtx_internal_imp_t*` – PeterT Apr 30 '19 at 10:11
  • I tried, but where do I find what's inside it? It does not seem to be defined anywhere in public sources. – riv Apr 30 '19 at 10:21
  • Does that mean I can't find the locking thread even knowing the internal details? That seems to be a major hurdle when debugging multithreaded apps. – riv Apr 30 '19 at 10:24
  • 3
    @riv nah, it uses an SRWLock for locking but it also additionally stores the threadid you can see that in `\crt\src\stl\mutex.c` – PeterT Apr 30 '19 at 10:31
  • Ah thanks that solves the issue. I could put this in a natvis next time I run into this issue. – riv Apr 30 '19 at 10:55

2 Answers2

12

Thanks to @PeterT's comment, wrote a visualizer for various mutex types (place in /Documents/Visual Studio 2017/Visualizers/mutex.natvis):

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
  <Type Name="std::_Mutex_base">
    <Expand>
      <Item Name="[thread_id]">*(long*)((char*)&amp;_Mtx_storage+sizeof(_Mtx_storage)-8)</Item>
      <Item Name="[count]">*(int*)((char*)&amp;_Mtx_storage+sizeof(_Mtx_storage)-4)</Item>
    </Expand>    
  </Type>
  <Type Name="std::mutex">
    <DisplayString>mutex</DisplayString>
    <Expand>
      <ExpandedItem>(_Mutex_base*)this</ExpandedItem>
    </Expand>
  </Type>
  <Type Name="std::timed_mutex">
    <DisplayString>timed_mutex</DisplayString>
    <Expand>
      <Item Name="[locked]">_My_locked</Item>
    </Expand>
  </Type>
  <Type Name="std::recursive_mutex">
    <DisplayString>recursive_mutex</DisplayString>
    <Expand>
      <ExpandedItem>(_Mutex_base*)this</ExpandedItem>
    </Expand>
  </Type>
  <Type Name="std::recursive_timed_mutex">
    <DisplayString>recursive_timed_mutex</DisplayString>
    <Expand>
      <Item Name="[locked]">_My_locked</Item>
      <Item Name="[owner]">_My_owner</Item>
    </Expand>
  </Type>
</AutoVisualizer> 
riv
  • 6,846
  • 2
  • 34
  • 63
0

Using visual studio 2019:

If you find yourself in a lockup using std::mutex. Show external code and go to... mtx_do_lock() in the call stack (probably 3 calls up from user code) and from here hover over mtx paramenter. This will show the owning thread id it is waiting for.