[英]helgrind in valgrind complains with simple mutex
我正在調試一些線程代碼,並使用valgrind --tool = helgrind,由於某種原因,helgrind不喜歡下面的簡單示例。
在啟動線程之前,先鎖定互斥鎖。 在線程的末尾,我要解鎖,從而通過假定互斥對象將被鎖定直到線程完成,從而確保一次只能運行一個線程。
根據valgrind為什么這無效?
這是一個更大程序的一部分,我的主程序正在讀取/解析數據,它將啟動一個分析線程,但是我只希望一次運行一個分析線程。
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex;
void *inner(void *ptr){
size_t threadid=(size_t)ptr;
int sleepval = lrand48() % 5 +1;
fprintf(stderr,"thread: %lu will wait:%d\n",threadid,sleepval);fflush(stderr);
sleep(sleepval);
pthread_mutex_unlock(&mutex);
}
int outer(size_t ntimes){
pthread_t thread1;
size_t i;
for(i=0;i<ntimes;i++){
pthread_mutex_lock(&mutex);
if(pthread_create( &thread1, NULL, inner, (void*) i))
fprintf(stderr,"Problems creating thread\n");
}
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
int main(){
pthread_mutex_init(&mutex, NULL);
outer(3);
return 0;
}
==8326== Helgrind, a thread error detector
==8326== Copyright (C) 2007-2013, and GNU GPL'd, by OpenWorks LLP et al.
==8326== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==8326== Command: ./a.out
==8326==
thread: 0 will wait:1
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #1 is the program's root thread
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Attempt to re-lock a non-recursive lock I already hold
==8326== at 0x4C32010: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326== Lock was previously acquired
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #2 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #2 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Bug in libpthread: recursive write lock granted on mutex/wrlock which does not support recursion
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
thread: 1 will wait:4
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #3 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #3 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
thread: 2 will wait:1
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Attempt to re-lock a non-recursive lock I already hold
==8326== at 0x4C32010: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009B1: outer (threadTest.c:25)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326== Lock was previously acquired
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400959: outer (threadTest.c:21)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ---Thread-Announcement------------------------------------------
==8326==
==8326== Thread #4 was created
==8326== at 0x515543E: clone (clone.S:74)
==8326== by 0x4E44199: do_clone.constprop.3 (createthread.c:75)
==8326== by 0x4E458BA: pthread_create@@GLIBC_2.2.5 (createthread.c:245)
==8326== by 0x4C30C90: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400976: outer (threadTest.c:22)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #4 unlocked lock at 0x6010A0 currently held by thread #1
==8326== at 0x4C325C0: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x400937: inner (threadTest.c:11)
==8326== by 0x4C30E26: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4E45181: start_thread (pthread_create.c:312)
==8326== by 0x515547C: clone (clone.S:111)
==8326== Lock at 0x6010A0 was first observed
==8326== at 0x4C31DDA: pthread_mutex_init (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009D0: main (threadTest.c:31)
==8326==
==8326== ----------------------------------------------------------------
==8326==
==8326== Thread #1: Bug in libpthread: recursive write lock granted on mutex/wrlock which does not support recursion
==8326== at 0x4C32145: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==8326== by 0x4009B1: outer (threadTest.c:25)
==8326== by 0x4009DA: main (threadTest.c:32)
==8326==
==8326==
==8326== For counts of detected and suppressed errors, rerun with: -v
==8326== Use --history-level=approx or =none to gain increased speed, at
==8326== the cost of reduced accuracy of conflicting-access information
==8326== ERROR SUMMARY: 9 errors from 7 contexts (suppressed: 104 from 61)
在pthread_mutex_lock
的手冊頁中:
如果線程嘗試解鎖尚未鎖定的互斥鎖或已解鎖的互斥鎖,則會導致未定義的行為。
因此,您必須在同一線程中鎖定和解鎖互斥鎖。
同樣,您的函數應返回與原型匹配的值。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t mutex;
void *inner(void *ptr){
size_t threadid = *(size_t *)ptr;
int sleepval = rand() % 5 +1;
pthread_mutex_lock(&mutex);
fprintf(stderr,"thread: %lu will wait:%d\n",threadid,sleepval);
fflush(stderr);
sleep(sleepval);
pthread_mutex_unlock(&mutex);
return NULL;
}
int outer(size_t ntimes){
pthread_t thread[ntimes];
size_t i, id[ntimes];
for(i=0;i<ntimes;i++){
id[i] = i;
if(pthread_create(thread + i, NULL, inner, &id[i]))
fprintf(stderr,"Problems creating thread\n");
}
for(i=0;i<ntimes;i++)
pthread_join(thread[i], NULL);
return 0;
}
int main(void){
pthread_mutex_init(&mutex, NULL);
outer(3);
return 0;
}
這對我有用。 我還添加了缺少的標題,並更改了功能參數以匹配新要求。
旁注: outer
函數現在使用可變長度數組,因此它僅在C99中起作用,而在C ++中不起作用(該問題被標記為兩者)。
直接的問題是您將一個互斥鎖鎖定在一個線程中,然后將其解鎖在另一個線程中。 您還嘗試在同一線程中兩次鎖定同一非遞歸互斥體。 因為只有獲得了鎖的線程才能釋放它,所以它將成為死鎖。
要實現您想要的感覺,您可以只加入新創建的線程:連接將阻塞,直到相應的線程退出。
或者,您可以保護活動線程數,該線程數不會因創建線程而增加,而隨着線程結束時間而遞減。 精加工線程還將發出條件變量信號。 如果計數太高,創建線程將檢查計數並等待條件變量。
擁有一個在工作隊列中使用並可能阻塞的處理器線程可能是限制工作線程數量的最簡單,最有效的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.