C 如何从pthread_join()获取错误代码?

C 如何从pthread_join()获取错误代码?,c,multithreading,pthreads,errno,pthread-join,C,Multithreading,Pthreads,Errno,Pthread Join,以下代码无法加入pthreads,并打印消息“join failed”。如何获得有关故障及其原因的更多信息 pthread_t aThread[MAX_LENGTH]; int errCode[MAX_LENGTH]; char returnVal; for(int i = 0; i < MAX_LENGTH; i++) { if((errCode[i] = pthread_create(&aThread[i], NULL, &am

以下代码无法加入pthreads,并打印消息“join failed”。如何获得有关故障及其原因的更多信息

pthread_t aThread[MAX_LENGTH];
    int errCode[MAX_LENGTH];
    char returnVal;    
for(int i = 0; i < MAX_LENGTH; i++)
    {

        if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
            printf("error creating thread %d\n", errCode[i]);
        if(!pthread_join(aThread[i], (void**)&returnVal))
            printf("join failed\n i is %d", i);
    }
pthread_t aThread[MAX_LENGTH];
int errCode[最大长度];
charreturnval;
对于(int i=0;i

编辑:实际加入返回了
无错误
,我犯了一个错误。if语句不应该有
因为如果存在计算结果为true的问题,join将返回一个非零的数字。

我是否遗漏了什么?返回值告诉您错误:

返回值 如果成功,pthread_join()函数将返回零。否则,, 将返回一个错误号以指示错误

错误 pthread_join()将在以下情况下失败:

 [EDEADLK]          A deadlock was detected or the value of thread speci-
                    fies the calling thread.

 [EINVAL]           The implementation has detected that the value speci-
                    fied by thread does not refer to a joinable thread.

 [ESRCH]            No thread could be found corresponding to that speci-
                    fied by the given thread ID, thread.
当函数失败时(即在任何pthread调用中,返回代码不等于零),它会将
errno
设置为失败原因的值。有几种方法可以获得故障代码的文本解释

int returnval;

if((returnval = pthread_join(aThread[i], (void**)&returnVal)) != 0)
{
    printf("error joining thread: %s\n", strerror(returnval));  //1st optiop

    perror("error joining thread:");  //2nd option

    printf("error joining thread: %m\n");  //3rd option

}
(1)
strerror
将打印您传递的错误值的错误字符串,并且便于放入printf语句中

(2)
perror
允许您传递一个小字符串,该字符串将首先打印,然后它将自动打印设置为
errno
的任何值的错误描述。您不需要显式地传递
errno

(3) 对
printf
有一个glibc扩展,它提供了一个
%m
转换说明符,其作用类似于
strerror
,但不太麻烦。这是最不便于携带的


一旦您得到了描述,您就可以轻松查看失败呼叫的手册页,它们将提供关于呼叫失败原因的更多提示。Charlie Burns已经发布了线程连接可能失败的原因。

我在评论中指出了这一点,但它值得详述

您的
returnVal
用法错误

pthread\u join
api需要一个
void**
,它是指向
void*
的指针。与
void*
不同,
void**
并非同样通用。它是一个特定类型的指针,因此您应该只传递一个类似类型的地址。但是,您无论如何都没有使用它,所以我建议您现在只传递NULL。如前所述,它是未定义的行为。我可以向您保证,
sizeof(char)
,您提供给它的地址的可写大小,以及
sizeof(void*)
,它期望的可用大小,是不同的。现在来考虑这个问题:

pthread_join(aThread[i], NULL);
如果您想知道该
void**
参数的用途,它是存储线程进程返回值的地方。回想一下,pthread线程过程如下所示:

void* thread_proc(void* args)
// ^----- this is what is stashed in the pthread_join second parameter
pthread_t aThread[MAX_LENGTH];
int errCode[MAX_LENGTH] = {0};

for (int i = 0; i < MAX_LENGTH; i++)
{
    if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
        printf("error creating thread %d, error=%d\n", i, errCode[i]);
}

for (int i = 0; i < MAX_LENGTH; i++)
{
    // note the check for errCode[i], which is only non-zero 
    //  if the i'th thread failed to start
    if(errCode[i] == 0)
    {
        errCode[i] = pthread_join(aThread[i], NULL))
        if (errCode[i] != 0)
            printf("error joining thread %d, error=%d\n", i, errCode[i]);
    }
}

失败测试的逻辑是向后的

pthread\u join
函数在成功时返回
0
;不是因为失败


您实际上没有运行并发线程

线程并发仅仅意味着线程同时运行。但你的不是。您启动一个线程,然后等待它结束,然后启动一个线程,然后等待它结束,等等。这实际上并不比简单地调用一个函数好(事实上,更糟)。如果希望线程同时运行,则逻辑的样式应如下所示:

void* thread_proc(void* args)
// ^----- this is what is stashed in the pthread_join second parameter
pthread_t aThread[MAX_LENGTH];
int errCode[MAX_LENGTH] = {0};

for (int i = 0; i < MAX_LENGTH; i++)
{
    if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
        printf("error creating thread %d, error=%d\n", i, errCode[i]);
}

for (int i = 0; i < MAX_LENGTH; i++)
{
    // note the check for errCode[i], which is only non-zero 
    //  if the i'th thread failed to start
    if(errCode[i] == 0)
    {
        errCode[i] = pthread_join(aThread[i], NULL))
        if (errCode[i] != 0)
            printf("error joining thread %d, error=%d\n", i, errCode[i]);
    }
}
pthread_t aThread[MAX_LENGTH];
int errCode[MAX_LENGTH]={0};
对于(int i=0;i
更具体地说:

int retVal = pthread_create(&myThread, NULL,myThreadFn, NULL);
printf("error joining thread: %d\n", retVal);

pthread库不会在出错时设置errno变量。错误代码由函数返回。 Linux下的联机手册对pthread函数(例如)非常清楚,因为“返回值”部分通常包含以下内容:

返回值

成功时,pthread_join()返回0;出错时,它返回一个错误号

如果需要通过strerror()strerror\u r()%mprintf format()等函数输出错误,则必须在错误分支中使用失败服务的返回码或更新errno

if ((rc = pthread_join(...)) != 0) {
  errno = rc;
  fprintf(stderr, "pthread_join(): %m\n");
 OR
  fprintf(stderr, "pthread_join(): %m\n", strerror(errno)); // rc could be used without errno
 OR
  char err_buf[128];
  errno = rc;
  fprintf(stderr, "pthread_join(): %m\n", strerror_r(errno, err_buf, sizeof(err_buf))); // rc could be used without errno
注释

  • errno是线程安全的(它位于线程本地存储中)。因此,它对每个线程都是本地的
  • strerror\u r()%m应在多线程环境中使用,因为它们是线程安全的(strerror()不是)

将您的
returnVal
地址转换为
void**
是未定义的行为。除非系统上的
sizeof(char)==sizeof(void*)
(我可以向您保证它不是),否则看起来您无论如何都不会使用它,并且NULL是一个可行的选项,所以您可以选择
pthread\u join(aThread[I],NULL)
此外,
pthread\u join
在成功时返回零(0),因此使用
测试它是否失败是向后的。最后,无论如何,你不想这样做,你想开始他们所有人,