如何取消时收集线程退出状态(使用连接)

问题描述 投票:0回答:1

我正在尝试取消来自调用方或被调用方的线程,但是两者都导致程序崩溃

但是如果我加入,我将获得正确的退出状态。

如何正确收集pthread_cancel上的退出状态

手册页如下

被取消的线程终止后,使用pthread_join(3)获得PTHREAD_CANCELED作为线程的退出状态。(加入线程是知道取消具有已完成。)

#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());
}
c pthreads
1个回答
0
投票

如果取消线程(在正常终止之前),那么当您加入它时,您将收到PTHREAD_CANCELED作为线程的返回值/退出状态。该宏扩展为返回的实际void *值,因此您可以将接收到的值直接与该值进行比较,以判断线程是否被取消。通常,它不是valid指针,因此您不得尝试取消引用它。

示例:

    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手册页的措辞有点快速和松散。从进程的意义上讲,线程不具有“退出状态”,并且实际的POSIX规范在线程上下文中不使用该术语。例如,the POSIX specifications for pthread_join()说:

[成功返回带有非NULL pthread_join()参数的pthread_join()调用后,终止线程传递给value_ptr的值应在pthread_exit()引用的位置可用。

与Linux的措辞相比,这有点令人mouth舌,但它被选择为非常精确。

也请注意,此处选择value_ptr类型是有意且有用的。打包void *不仅是一种钝器。通过这样的指针,线程可以提供对任何类型对象的访问,这对于传达有关其计算结果的信息可能是有用的。另一方面,线程避开这种可能性并只返回int是相当普遍的。但是,如果线程确实希望以这种方式提供整数代码,则它很可能会提供NULLcast to类型int,而不是指向包含以下内容的void *类型对象的指针选择的值。在这种情况下,可以通过强制返回int而不是通过取消引用指针来获取值。

© www.soinside.com 2019 - 2024. All rights reserved.