Helgrind: a thread error detector
Thread #6: lock order "0x6010C0 before 0x601160" violated
Observed (incorrect) order is: acquisition of lock at 0x601160
(stack unavailable)
followed by a later acquisition of lock at 0x6010C0
at 0x4C2BC62: pthread_mutex_lock (hg_intercepts.c:494)
by 0x4007DE: dine (tc14_laog_dinphils.c:19)
by 0x4C2CBE7: mythread_wrapper (hg_intercepts.c:219)
by 0x4E369C9: start_thread (pthread_create.c:300)
7.4. Detected errors: Data Races
A data race happens, or could happen, when two threads access a shared memory location without using suitable locks
or other synchronisation to ensure single-threaded access. Such missing locking can cause obscure timing dependent
bugs. Ensuring programs are race-free is one of the central difficulties of threaded programming.
Reliably detecting races is a difficult problem, and most of Helgrind’s internals are devoted to dealing with it. We
begin with a simple example.
7.4.1. A Simple Data Race
About the simplest possible example of a race is as follows. In this program, it is impossible to know what the value
of
var
is at the end of the program. Is it 2 ? Or 1 ?
#include <pthread.h>
int var = 0;
void* child_fn ( void* arg ) {
var++; /* Unprotected relative to parent */ /* this is line 6 */
return NULL;
}
int main ( void ) {
pthread_t child;
pthread_create(&child, NULL, child_fn, NULL);
var++; /* Unprotected relative to child */ /* this is line 13 */
pthread_join(child, NULL);
return 0;
}
The problem is there is nothing to stop
var
being updated simultaneously by both threads. A correct program would
protect
var
with a lock of type
pthread_mutex_t
, which is acquired before each access and released afterwards.
Helgrind’s output for this program is:
109