如何从pthread_join获取错误代码

时间:2013-10-10 03:44:05

标签: c pthreads pthread-join

以下代码无法创建连接pthread,并且会打印消息“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);
    }

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

5 个答案:

答案 0 :(得分:4)

我在评论中指出了这一点,但值得放大。

returnVal使用错误

pthread_join api需要void**,这是指向void*的指针。与void*不同,void**并非普遍存在。它是特定类型的指针,因此您只应传递同样类型的地址。但是,你还没有使用它,所以我建议你现在只需传递NULL。如上所述,它是未定义的行为。而且我可以保证你sizeof(char),你给它的地址的可写大小,sizeof(void*),它预期可用的大小,相同。现在考虑一下这个:

pthread_join(aThread[i], NULL);

如果您想知道该void**参数的用途是什么,它是一个存储来自您的thread-proc的void*返回值的地方。回想一下pthread thread-proc看起来像这样:

void* thread_proc(void* args)
// ^----- this is what is stashed in the pthread_join second parameter

您的失败测试逻辑是向后的

pthread_join函数在成功上返回0;没有失败。


您实际上并未运行并发线程

线程并发只是意味着你的线程同时运行 。但你的不是。你启动一个线程,然后等待它结束,然后启动一个线程,然后等待它结束,等等。这实际上并不比简单地调用一个更好(事实上,实际上更糟)功能。如果您希望线程同时运行 ,您的逻辑应该像这样设置:

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]);
    }
}

答案 1 :(得分:2)

当函数失败时(即在任何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发布了pthread_join可能失败的原因。

答案 2 :(得分:0)

我错过了什么吗?返回值告诉您错误:

返回值      如果成功,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.

答案 3 :(得分:0)

更具体地说::

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

答案 4 :(得分:0)

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

返回值

成功时,pthread_join()返回0;否则,返回0。如果出错,则返回错误号。

如果您需要通过 strerror() strerror_r()%m printf格式({{3 }}),您必须使用失败服务的返回码或在错误分支中更新 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_r()%m 应该在多线程环境中使用,因为它们是线程安全的( strerror()不是)