Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) deadlock

 

A deadlock occurs when all the threads of a program are waiting for a mutex.

 

Below is an example of causing a deadlock, followed by using tools to detect it.

 

 

 

 

 

Example

 

The example below will end in a deadlock: a thread calls the member function MyClass::DoIt. This member function acquires the class its only mutex. Then, MyClass::DoIt calls MyClass::DoItAgain, which starts by acquiring the same mutex. Because this mutex is already in use, the program will wait infinitely.

 

 

#include <iostream>
#include <thread>
#include <regex>
#include <boost/bind.hpp>

struct MyClass
{
  void DoIt()
  {
    ///Acquire single access
    std::lock_guard<std::mutex> lock(m_mutex);

    ///Use of std::clog to write to screen directly
    std::clog << __func__ << '\n';

    ///Causes deadlock: DoItAgain wants to acquire m_mutex, which is in use already!
    DoItAgain();
  }

  private:
  void DoItAgain()
  {
    ///Causes deadlock: m_mutex is in use already!
    std::lock_guard<std::mutex> lock(m_mutex);

    ///Use of std::clog to write to screen directly
    std::clog << __func__ << '\n';
  }

  ///The MyClass mutex
  static std::mutex m_mutex;
};

std::mutex MyClass::m_mutex;

int main()
{
  ///Create the class that will cause a deadlock
  MyClass my_class;

  ///Create a thread that calls the class its method that will cause a deadlock
  std::thread t(boost::bind(&MyClass::DoIt,my_class));

  ///Due to deadlock, it will take forever to wait until t has finished
  t.join();
}

 

Screen output:

 

DoIt

 

The problem in this example can be solved by using a std::recursive_mutex instead.

 

 

 

 

 

OKAY Detecting a deadlock using DRD

 

Detecting a deadlock using DRD gives an indication of the problem. DRD calls the program like this:

 

#!/bin/sh
valgrind --tool=drd --log-file=helgrind.txt ../CppDeadlock-build-desktop/./CppDeadlock

 

After terminating the program by CTRL-C, the following output is generated by DRD:

 

==8958== drd, a thread error detector
==8958== Copyright (C) 2006-2010, and GNU GPL'd, by Bart Van Assche.
==8958== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==8958== Command: ../CppDeadlock-build-desktop/./CppDeadlock
==8958== Parent PID: 8957
==8958==
==8958== Thread 2:
==8958== Recursive locking not allowed: mutex 0x804c194, recursion count 1, owner 2.
==8958==    at 0x40295E0: pthread_mutex_lock (drd_pthread_intercepts.c:584)
==8958==    by 0x80494EF: MyClass::DoIt() (in /home/richel/Projects/Website/CppDeadlock-build-desktop/CppDeadlock)
==8958==    by 0x4399265: ??? (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14)
==8958==    by 0x4027E8B: vgDrd_thread_wrapper (drd_pthread_intercepts.c:281)
==8958==    by 0x4027E8B: vgDrd_thread_wrapper (drd_pthread_intercepts.c:281)
==8958==    by 0x42E1E98: start_thread (pthread_create.c:304)
==8958==    by 0x44F273D: clone (clone.S:130)
==8958== mutex 0x804c194 was first observed at:
==8958==    at 0x40295E0: pthread_mutex_lock (drd_pthread_intercepts.c:584)
==8958==    by 0x804949C: MyClass::DoIt() (in /home/richel/Projects/Website/CppDeadlock-build-desktop/CppDeadlock)
==8958==    by 0x4399265: ??? (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14)
==8958==    by 0x4027E8B: vgDrd_thread_wrapper (drd_pthread_intercepts.c:281)
==8958==    by 0x4027E8B: vgDrd_thread_wrapper (drd_pthread_intercepts.c:281)
==8958==    by 0x42E1E98: start_thread (pthread_create.c:304)
==8958==    by 0x44F273D: clone (clone.S:130)
==8958==

 

 

 

 

 

FAIL Detecting a deadlock using helgrind

 

Detecting a deadlock using helgrind fails. helgrind calls the program like this:

 

#!/bin/sh
valgrind --tool=helgrind --log-file=helgrind.txt ../CppDeadlock-build-desktop/./CppDeadlock

 

After terminating the program by CTRL-C, the following output is generated by helgrind:

 

==1649== Helgrind, a thread error detector
==1649== Copyright (C) 2007-2010, and GNU GPL'd, by OpenWorks LLP et al.
==1649== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==1649== Command: ../CppDeadlock-build-desktop/./CppDeadlock
==1649== Parent PID: 1648
==1649==

 

 

 

 

 

FAIL Detecting a deadlock using memcheck

 

Detecting a deadlock using memcheck fails. memcheck calls the program like this:

 

#!/bin/sh
valgrind --leak-check=full -v --show-reachable=yes --log-file=memcheck.txt ../CppDeadlock-build-desktop/./CppDeadlock

 

After terminating the program by CTRL-C, the following output is generated by memcheck:

 

==8769== Memcheck, a memory error detector
==8769== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==8769== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==8769== Command: ../CppDeadlock-build-desktop/./CppDeadlock
==8769== Parent PID: 8768
==8769==
--8769--
--8769-- Valgrind options:
--8769--    --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--8769--    --leak-check=full
--8769--    -v
--8769--    --show-reachable=yes
--8769--    --log-file=memcheck.txt
--8769-- Contents of /proc/version:
--8769--   Linux version 2.6.38-11-generic-pae (buildd@rothera) (gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) ) #48-Ubuntu SMP Fri Jul 29 20:51:21 UTC 2011
--8769-- Arch and hwcaps: X86, x86-sse1-sse2
--8769-- Page sizes: currently 4096, max supported 4096
--8769-- Valgrind library directory: /usr/lib/valgrind
--8769-- Reading syms from /lib/i386-linux-gnu/ld-2.13.so (0x4000000)
--8769--   Considering /lib/i386-linux-gnu/ld-2.13.so ..
--8769--   .. CRC mismatch (computed 2a2c2799 wanted 1e351f1f)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/ld-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /home/richel/Projects/Website/CppDeadlock-build-desktop/CppDeadlock (0x8048000)
--8769-- Reading syms from /usr/lib/valgrind/memcheck-x86-linux (0x38000000)
--8769--    object doesn't have a dynamic symbol table
--8769-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--8769-- Reading suppressions file: /usr/lib/valgrind/default.supp
--8769-- REDIR: 0x4016a80 (index) redirected to 0x3803f82b (vgPlain_x86_linux_REDIR_FOR_index)
--8769-- Reading syms from /usr/lib/valgrind/vgpreload_core-x86-linux.so (0x4020000)
--8769-- Reading syms from /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so (0x4023000)
==8769== WARNING: new redirection conflicts with existing -- ignoring it
--8769--     new: 0x04016a80 (index               ) R-> 0x04026c78 index
--8769-- REDIR: 0x4016c20 (strlen) redirected to 0x4027048 (strlen)
--8769-- Reading syms from /usr/lib/libQtCore.so.4.7.2 (0x4044000)
--8769--   Considering /usr/lib/libQtCore.so.4.7.2 ..
--8769--   .. CRC mismatch (computed 5d0d89bc wanted b4e02a1a)
--8769--   Considering /usr/lib/debug/usr/lib/libQtCore.so.4.7.2 ..
--8769--   .. CRC is valid
--8769-- Reading syms from /lib/i386-linux-gnu/libpthread-2.13.so (0x42d7000)
--8769--   Considering /lib/i386-linux-gnu/libpthread-2.13.so ..
--8769--   .. CRC mismatch (computed 87269ed5 wanted 7df95f2f)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/libpthread-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14 (0x42f0000)
--8769--    object doesn't have a symbol table
--8769-- Reading syms from /lib/i386-linux-gnu/libm-2.13.so (0x43db000)
--8769--   Considering /lib/i386-linux-gnu/libm-2.13.so ..
--8769--   .. CRC mismatch (computed e686ed93 wanted a0f1e52c)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/libm-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /lib/i386-linux-gnu/libgcc_s.so.1 (0x4401000)
--8769--   Considering /lib/i386-linux-gnu/libgcc_s.so.1 ..
--8769--   .. CRC mismatch (computed 3fa6d24f wanted 8b2bf89f)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/libgcc_s.so.1 ..
--8769--   .. CRC is valid
--8769-- Reading syms from /lib/i386-linux-gnu/libc-2.13.so (0x441d000)
--8769--   Considering /lib/i386-linux-gnu/libc-2.13.so ..
--8769--   .. CRC mismatch (computed 97e88cd2 wanted 4635a554)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /lib/i386-linux-gnu/libz.so.1.2.3.4 (0x457f000)
--8769--   Considering /lib/i386-linux-gnu/libz.so.1.2.3.4 ..
--8769--   .. CRC mismatch (computed 995eb12f wanted 33a06a21)
--8769--    object doesn't have a symbol table
--8769-- Reading syms from /lib/i386-linux-gnu/libdl-2.13.so (0x4594000)
--8769--   Considering /lib/i386-linux-gnu/libdl-2.13.so ..
--8769--   .. CRC mismatch (computed 608d0daf wanted 983d6578)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/libdl-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /usr/lib/i386-linux-gnu/libgthread-2.0.so.0.2800.6 (0x4598000)
--8769--   Considering /usr/lib/i386-linux-gnu/libgthread-2.0.so.0.2800.6 ..
--8769--   .. CRC mismatch (computed 244482a3 wanted 61a9cd3c)
--8769--    object doesn't have a symbol table
--8769-- Reading syms from /lib/i386-linux-gnu/librt-2.13.so (0x459d000)
--8769--   Considering /lib/i386-linux-gnu/librt-2.13.so ..
--8769--   .. CRC mismatch (computed 680ec6ea wanted 247d4d27)
--8769--   Considering /usr/lib/debug/lib/i386-linux-gnu/librt-2.13.so ..
--8769--   .. CRC is valid
--8769-- Reading syms from /lib/i386-linux-gnu/libglib-2.0.so.0.2800.6 (0x45a6000)
--8769--   Considering /lib/i386-linux-gnu/libglib-2.0.so.0.2800.6 ..
--8769--   .. CRC mismatch (computed 2312631e wanted e21a44de)
--8769--    object doesn't have a symbol table
--8769-- Reading syms from /lib/i386-linux-gnu/libpcre.so.3.12.1 (0x467e000)
--8769--   Considering /lib/i386-linux-gnu/libpcre.so.3.12.1 ..
--8769--   .. CRC mismatch (computed 9e5ab3c1 wanted 29aaf7e3)
--8769--    object doesn't have a symbol table
--8769-- REDIR: 0x4490fb0 (strncmp) redirected to 0x4020479 (_vgnU_ifunc_wrapper)
--8769-- REDIR: 0x4498140 (strstr) redirected to 0x4020479 (_vgnU_ifunc_wrapper)
--8769-- REDIR: 0x4497db0 (__GI_strstr) redirected to 0x4028ef1 (strstr)
--8769-- REDIR: 0x44910b0 (rindex) redirected to 0x4026acc (rindex)
--8769-- REDIR: 0x439c650 (operator new(unsigned int)) redirected to 0x4026398 (operator new(unsigned int))
--8769-- REDIR: 0x448cef0 (malloc) redirected to 0x40267df (malloc)
--8769-- REDIR: 0x4490d80 (__GI_strlen) redirected to 0x402702d (__GI_strlen)
--8769-- REDIR: 0x4490740 (strcmp) redirected to 0x4020479 (_vgnU_ifunc_wrapper)
--8769-- REDIR: 0x4539cb0 (__strcmp_ssse3) redirected to 0x40279d0 (strcmp)
--8769-- REDIR: 0x448de70 (calloc) redirected to 0x4025235 (calloc)

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict