C 如何从pthread_join()获取错误代码?
以下代码无法加入pthreads,并打印消息“join failed”。如何获得有关故障及其原因的更多信息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
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),因此使用测试它是否失败代码>是向后的。最后,无论如何,你不想这样做,你想开始他们所有人,