Valgrind (Helgrind):可能的数据竞争调试

问题描述 投票:0回答:1

有人可以帮我弄清楚这是否真的是我的错误造成的,或者因为 helgrind 在这种情况下无法正确追踪它?

我也想知道“在...”是什么意思。在这种情况下是

at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
。这是否意味着条件在那里找到并且由于这不是我编写的函数,所以这不是我的错?

我可以修复任何竞争条件错误,但这个错误。

编辑开始:

如果有帮助,我在this repo中有完整的代码: 只需构建和测试:

git clone https://github.com/mortytheshorty/thread && cd thread
mkdir build && cd build
cmake ..
make
valgrind -tool=helgrind -s ./simple_thread_test

测试功能:

void *thread_test(void *arg)
{
    struct timespec timespec = { 0 };
    timespec.tv_nsec = CLOCKS_PER_SEC * 500;
    char *p = arg;
    while(*p++) {
        printf("%s\n", (char *) arg);
        nanosleep(&timespec, NULL);
    }
}

编辑结束

标题:

// (c) 2023 Florian Giest
// This code is licensed under MIT license (see LICENSE.txt for details)

#ifndef _DEBUG_H// BEGIN INCLUDE GUARD
#define _DEBUG_H

/*********************************************************************************************************/
/*                                              DEPENDANICIES                                            */
/*********************************************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <pthread.h>

/*********************************************************************************************************/
/*                                               DEFINITIONS                                             */
/*********************************************************************************************************/

/* if DEBUG is defines it enables the macro for logging the steps 
   of every function which calls these functions/macros */
#ifdef DEBUG
 /* pretty simple debug function expaned by macro 'debug()'
    write DEBUG: at the first place followed by the calling pthread id
    and a formatstring and its arguments
 */
 void xdebug(pthread_t threadid, const char *function, const char *fmt, ...);
 #define debug(fmt, ...) xdebug(pthread_self(), __func__, fmt, ##__VA_ARGS__)
 /* same as for 'xdebug()' but for error and also prints errno string if
    errno is set.
 */
 void xdebug_error(pthread_t threadid, const char *function, const char *fmt, ...);
 #define debug_error(fmt, ...) xdebug_error(pthread_self(), __func__, fmt, ##__VA_ARGS__)
#else
 #define debug_error(x, ...)
 #define debug(x, ...)
#endif


/*********************************************************************************************************/
/*                                           FUNCTION DEFINITIONS                                        */
/*********************************************************************************************************/

#endif

代码:

// (c) 2023 Florian Giest
// This code is licensed under MIT license (see LICENSE.txt for details)

/*********************************************************************************************************/
/*                                              DEPENDANICIES                                            */
/*********************************************************************************************************/

#include <pthread.h>

/*********************************************************************************************************/
/*                                               DEFINITIONS                                             */
/*********************************************************************************************************/

pthread_mutex_t debugmtx = PTHREAD_MUTEX_INITIALIZER;

/*********************************************************************************************************/
/*                                           FUNCTION DEFINITIONS                                        */
/*********************************************************************************************************/

void xdebug(pthread_t threadid, const char *function, const char *fmt, ...)
{
    pthread_mutex_lock(&debugmtx);
    va_list args;
    va_start(args, fmt);

    fprintf(stdout, "DEBUG: thread[%ld] %s(): ", threadid, function);
    vfprintf(stdout, fmt, args);
    fputc('\n', stdout);

    va_end(args);
    pthread_mutex_unlock(&debugmtx);
}


void xdebug_error(pthread_t threadid, const char *function, const char *fmt, ...)
{
    pthread_mutex_lock(&debugmtx);
    va_list args;
    va_start(args, fmt);

    fprintf(stderr, "ERROR: thread[%ld] %s(): ", threadid, function);
    vfprintf(stderr, fmt, args);
    if(errno) {
        fprintf(stderr, " (%s)", strerror(errno));
    }
    fputc('\n', stderr);

    va_end(args);
    pthread_mutex_unlock(&debugmtx);
}

Valgrind(Helgrind)输出:

==30008==
==30008== 6 errors in context 1 of 2:
==30008== ----------------------------------------------------------------
==30008==
==30008==  Lock at 0x4856200 was first observed
==30008==    at 0x483FEDF: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4853939: xdebug (error.c:34)
==30008==    by 0x48530FC: thread_create (thread.c:156)
==30008==    by 0x109326: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==  Address 0x4856200 is 0 bytes inside data symbol "debugmtx"
==30008==
==30008== Possible data race during write of size 1 at 0x4A79045 by thread #2
==30008== Locks held: none
==30008==    at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4914631: _IO_new_file_xsputn (fileops.c:1236)
==30008==    by 0x4914631: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==30008==    by 0x49094F7: puts (ioputs.c:40)
==30008==    by 0x1092B5: thread_test (in /home/flo/projects/thread/build/simple_thread_test)
==30008==    by 0x48530A8: thread_worker (thread.c:126)
==30008==    by 0x4842B1A: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x486A608: start_thread (pthread_create.c:477)
==30008==    by 0x49A4132: clone (clone.S:95)
==30008==
==30008== This conflicts with a previous write of size 1 by thread #1
==30008== Locks held: 1, at address 0x4856200
==30008==    at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4914631: _IO_new_file_xsputn (fileops.c:1236)
==30008==    by 0x4914631: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==30008==    by 0x48FB971: __vfprintf_internal (vfprintf-internal.c:1373)
==30008==    by 0x48E6C69: fprintf (fprintf.c:32)
==30008==    by 0x4853992: xdebug (error.c:38)
==30008==    by 0x48529C6: jobqueue_push (jobqueue.c:114)
==30008==    by 0x4853517: thread_addjob (thread.c:264)
==30008==    by 0x109403: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==  Address 0x4a79045 is 5 bytes inside a block of size 1,024 alloc'd
==30008==    at 0x483C893: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4906D03: _IO_file_doallocate (filedoalloc.c:101)
==30008==    by 0x4916ECF: _IO_doallocbuf (genops.c:347)
==30008==    by 0x4915F2F: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:745)
==30008==    by 0x49146B4: _IO_new_file_xsputn (fileops.c:1244)
==30008==    by 0x49146B4: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==30008==    by 0x48FB971: __vfprintf_internal (vfprintf-internal.c:1373)
==30008==    by 0x48E6C69: fprintf (fprintf.c:32)
==30008==    by 0x4853992: xdebug (error.c:38)
==30008==    by 0x48530FC: thread_create (thread.c:156)
==30008==    by 0x109326: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==  Block was alloc'd by thread #1
==30008==
==30008==
==30008== 7 errors in context 2 of 2:
==30008== ----------------------------------------------------------------
==30008==
==30008==  Lock at 0x4856200 was first observed
==30008==    at 0x483FEDF: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4853939: xdebug (error.c:34)
==30008==    by 0x48530FC: thread_create (thread.c:156)
==30008==    by 0x109326: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==  Address 0x4856200 is 0 bytes inside data symbol "debugmtx"
==30008==
==30008== Possible data race during write of size 1 at 0x4A79046 by thread #1
==30008== Locks held: 1, at address 0x4856200
==30008==    at 0x48488A6: mempcpy (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4914631: _IO_new_file_xsputn (fileops.c:1236)
==30008==    by 0x4914631: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==30008==    by 0x48FB971: __vfprintf_internal (vfprintf-internal.c:1373)
==30008==    by 0x48E6C69: fprintf (fprintf.c:32)
==30008==    by 0x4853992: xdebug (error.c:38)
==30008==    by 0x485357F: thread_pause (thread.c:275)
==30008==    by 0x10939A: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==
==30008== This conflicts with a previous write of size 1 by thread #2
==30008== Locks held: none
==30008==    at 0x4915DC8: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:781)
==30008==    by 0x4909599: puts (ioputs.c:41)
==30008==    by 0x1092B5: thread_test (in /home/flo/projects/thread/build/simple_thread_test)
==30008==    by 0x48530A8: thread_worker (thread.c:126)
==30008==    by 0x4842B1A: ??? (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x486A608: start_thread (pthread_create.c:477)
==30008==    by 0x49A4132: clone (clone.S:95)
==30008==  Address 0x4a79046 is 6 bytes inside a block of size 1,024 alloc'd
==30008==    at 0x483C893: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so)
==30008==    by 0x4906D03: _IO_file_doallocate (filedoalloc.c:101)
==30008==    by 0x4916ECF: _IO_doallocbuf (genops.c:347)
==30008==    by 0x4915F2F: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:745)
==30008==    by 0x49146B4: _IO_new_file_xsputn (fileops.c:1244)
==30008==    by 0x49146B4: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1197)
==30008==    by 0x48FB971: __vfprintf_internal (vfprintf-internal.c:1373)
==30008==    by 0x48E6C69: fprintf (fprintf.c:32)
==30008==    by 0x4853992: xdebug (error.c:38)
==30008==    by 0x48530FC: thread_create (thread.c:156)
==30008==    by 0x109326: main (in /home/flo/projects/thread/build/simple_thread_test)
==30008==  Block was alloc'd by thread #1
==30008==
--30008--
--30008-- used_suppression:    238 helgrind-glibc2X-005 /usr/lib/x86_64-linux-gnu/valgrind/default.supp:963
--30008-- used_suppression:     36 helgrind-glibc2X-004 /usr/lib/x86_64-linux-gnu/valgrind/default.supp:949
==30008==
==30008== ERROR SUMMARY: 13 errors from 2 contexts (suppressed: 274 from 95)
c multithreading valgrind race-condition
1个回答
0
投票

Helgrind拦截像

memcpy
这样的函数,并在vgpreload_helgrind-amd64-linux.so中使用它自己的版本。

这与问题无关。

在我看来你还有另一个功能

thread_test
,它也在做一些 I/O。您没有发布该功能的来源。 Helgrind 说你没有任何锁。

尝试对您从

thread_test
.

调用的任何 I/O 使用相同的锁
© www.soinside.com 2019 - 2024. All rights reserved.