取消时如何收集线程退出状态(使用连接)
How collect thread exit status(using join) when cancelled
我正在尝试取消来自调用者或调用者的线程,但两者都使程序崩溃
但如果我加入,我的退出状态就会正确。
如何在 pthread_cancel
上正确收集退出状态
手册页如下所述
After a canceled thread has terminated, a join with that thread using
pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status.
(Joining with a thread is the only way to know that cancellation has
completed.)
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg);
int errNum = 3;
int main()
{
pthread_t t_id;
void *status;
// on success pthread_create return zero
if(pthread_create(&t_id,NULL,thread_func,NULL) != 0){
printf("thread creation failed\n");
return 0;
}
printf("thread created with id %u successfully\n",t_id);
// status will be collecting the pthread_exit value
// error numberis returned incase of error
// pthread_cancel(t_id);
if(pthread_join(t_id,&status) != 0){
printf("join failed\n");
}
printf("thread %u exited with code %d\n", t_id, *(int *)status);
return 0;
}
void *thread_func(void *arg)
{
printf("Inside thread_func :%u\n",pthread_self());
//the arguments of pthread_exit should not be from local space, as it will be collected in caller using join
//pthread_exit(&errNum);
// if we return it may cause seg fault as we are trying to print the value from ptr(status)
//return ;
pthread_cancel(pthread_self());
}
如果线程被取消(在它正常终止之前),那么当您加入它时,您将收到 PTHREAD_CANCELED
作为线程的 return 值/退出状态。该宏扩展为 returned 的实际 void *
值,因此您可以直接将收到的值与该值进行比较,以判断线程是否被取消。它通常不是 有效 指针,因此您不能尝试取消引用它。
示例:
void *status;
// ...
if (pthread_join(t_id, &status) != 0) {
// pthread_join failed
} else if (status == PTHREAD_CANCELED) {
// successfully joined a thread that was cancelled
// 'status' MUST NOT be dereferenced
} else {
// successfully joined a thread that terminated normally
// whether 'status' may be dereferenced or how else it may be
// used depends on the thread
}
值得注意的是,Linux 手册页的措辞有点过时和松散。在进程的意义上,线程没有 "exit status",并且实际的 POSIX 规范不在线程的上下文中使用该术语。例如,the POSIX specifications for pthread_join()
说:
On return from a successful pthread_join()
call with a non-NULL value_ptr
argument, the value passed to pthread_exit()
by the terminating thread shall be made available in the location referenced by value_ptr
.
与 Linux 的措辞相比,这有点啰嗦,但选择得非常准确。
另请注意,此处选择类型 void *
是有意且有用的。它不仅仅是一种打包 int
的笨方法。通过这样的指针,线程可以提供对任何类型对象的访问,这对于传达有关其计算结果的信息可能很有用。另一方面,线程回避这种可能性并且只是 return NULL
是相当普遍的。但是如果一个线程确实想以这种方式提供一个整数代码,那么它很可能会提供一个 int
值 转换为 类型 void *
,而不是一个指针到包含所选值的 int
类型的对象。在那种情况下,可以通过转换回 int
而不是通过取消引用指针来获取值。
我正在尝试取消来自调用者或调用者的线程,但两者都使程序崩溃
但如果我加入,我的退出状态就会正确。
如何在 pthread_cancel
手册页如下所述
After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status. (Joining with a thread is the only way to know that cancellation has completed.)
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg);
int errNum = 3;
int main()
{
pthread_t t_id;
void *status;
// on success pthread_create return zero
if(pthread_create(&t_id,NULL,thread_func,NULL) != 0){
printf("thread creation failed\n");
return 0;
}
printf("thread created with id %u successfully\n",t_id);
// status will be collecting the pthread_exit value
// error numberis returned incase of error
// pthread_cancel(t_id);
if(pthread_join(t_id,&status) != 0){
printf("join failed\n");
}
printf("thread %u exited with code %d\n", t_id, *(int *)status);
return 0;
}
void *thread_func(void *arg)
{
printf("Inside thread_func :%u\n",pthread_self());
//the arguments of pthread_exit should not be from local space, as it will be collected in caller using join
//pthread_exit(&errNum);
// if we return it may cause seg fault as we are trying to print the value from ptr(status)
//return ;
pthread_cancel(pthread_self());
}
如果线程被取消(在它正常终止之前),那么当您加入它时,您将收到 PTHREAD_CANCELED
作为线程的 return 值/退出状态。该宏扩展为 returned 的实际 void *
值,因此您可以直接将收到的值与该值进行比较,以判断线程是否被取消。它通常不是 有效 指针,因此您不能尝试取消引用它。
示例:
void *status;
// ...
if (pthread_join(t_id, &status) != 0) {
// pthread_join failed
} else if (status == PTHREAD_CANCELED) {
// successfully joined a thread that was cancelled
// 'status' MUST NOT be dereferenced
} else {
// successfully joined a thread that terminated normally
// whether 'status' may be dereferenced or how else it may be
// used depends on the thread
}
值得注意的是,Linux 手册页的措辞有点过时和松散。在进程的意义上,线程没有 "exit status",并且实际的 POSIX 规范不在线程的上下文中使用该术语。例如,the POSIX specifications for pthread_join()
说:
On return from a successful
pthread_join()
call with a non-NULLvalue_ptr
argument, the value passed topthread_exit()
by the terminating thread shall be made available in the location referenced byvalue_ptr
.
与 Linux 的措辞相比,这有点啰嗦,但选择得非常准确。
另请注意,此处选择类型 void *
是有意且有用的。它不仅仅是一种打包 int
的笨方法。通过这样的指针,线程可以提供对任何类型对象的访问,这对于传达有关其计算结果的信息可能很有用。另一方面,线程回避这种可能性并且只是 return NULL
是相当普遍的。但是如果一个线程确实想以这种方式提供一个整数代码,那么它很可能会提供一个 int
值 转换为 类型 void *
,而不是一个指针到包含所选值的 int
类型的对象。在那种情况下,可以通过转换回 int
而不是通过取消引用指针来获取值。