以下代码无法创建连接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会返回一个非零数字。
答案 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
注释: