Код: Выделить всё
#include
#include
#include
pthread_mutex_t mtx_test = PTHREAD_MUTEX_INITIALIZER;
int ga = 0;
void cleanup(void *arg)
{
pthread_mutex_lock(&mtx_test);
ga += 1;
pthread_mutex_unlock(&mtx_test);
printf("cleanup\n");
}
void* thr_fn(void * arg)
{
pthread_cleanup_push(cleanup, arg);
while(true)
{
pthread_mutex_lock(&mtx_test);
ga += 1;
pthread_mutex_unlock(&mtx_test);
sleep(1);
}
pthread_cleanup_pop(1);
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thr_fn, nullptr);
sleep(3);
pthread_cancel(tid);
pthread_mutex_lock(&mtx_test);
printf("ga: %d\n", ga);
pthread_mutex_unlock(&mtx_test);
pthread_join(tid, nullptr);
}
Код: Выделить всё
==================
WARNING: ThreadSanitizer: data race (pid=29924)
Write of size 4 at 0x5593bd535068 by thread T1:
#0 cleanup(void*) /tmp/test/test.cpp:10 (a.out+0x139b) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
#1 __pthread_cleanup_class::~__pthread_cleanup_class() /usr/include/pthread.h:578 (a.out+0x16c9) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
#2 thr_fn(void*) /tmp/test/test.cpp:25 (a.out+0x1493) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
#3 thr_fn(void*) /tmp/test/test.cpp:23 (a.out+0x147e) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
Previous read of size 4 at 0x5593bd535068 by main thread (mutexes: write M0):
#0 main /tmp/test/test.cpp:37 (a.out+0x153c) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
As if synchronized via sleep:
#0 sleep ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:383 (libtsan.so.2+0x58691) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
#1 thr_fn(void*) /tmp/test/test.cpp:23 (a.out+0x147e) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
Location is global 'ga' of size 4 at 0x5593bd535068 (a.out+0x4068)
Mutex M0 (0x5593bd535040) created at:
#0 pthread_mutex_lock ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1341 (libtsan.so.2+0x59a13) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
#1 thr_fn(void*) /tmp/test/test.cpp:20 (a.out+0x1438) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
Thread T1 (tid=29926, running) created by main thread at:
#0 pthread_create ../../../../src/libsanitizer/tsan/tsan_interceptors_posix.cpp:1022 (libtsan.so.2+0x5ac1a) (BuildId: 38097064631f7912bd33117a9c83d08b42e15571)
#1 main /tmp/test/test.cpp:31 (a.out+0x14fc) (BuildId: ad9c32e6694e2996bfed96f0eb507bec0278f791)
SUMMARY: ThreadSanitizer: data race /tmp/test/test.cpp:10 in cleanup(void*)
==================
И в обработчике очистки, и в основном — pthread_mutex_lock явно используется перед доступом к ga, обеспечивая взаимное исключение.
Предупреждение указывает на «гонку данных» в ga, но это кажется неверным, поскольку мьютекс гарантирует поточно-ориентированную работу. доступ.
Почему ThreadSanitizer в этом случае сообщает о гонке данных? Известно ли это ограничение ThreadSanitizer при использовании pthread_cancel и обработчиков очистки? Если да, то как я могу устранить или подавить это ложное срабатывание? Или в моем коде есть реальный недостаток, который я не замечаю?
Буду очень признателен за любую помощь или идеи! Спасибо!
Подробнее здесь: https://stackoverflow.com/questions/793 ... pthread-ca