pthread_cancel 线程阻塞问题

背景

一个模块频繁启动退出会出现退出阻塞的问题!
因为有特殊业务用同事非阻塞库有问题,所以我暂时用线程阻塞加pthread_cancel强制退出;
肯定就是这个线程退出阻塞,加日志跟踪之。。
怀疑在pthread_join,测试发现阻塞在pthread_cancel!!

分析

基本概念
pthread_cancel调用并不等待线程终止,它只提出请求。线程在取消请求(pthread_cancel)发出后会继续运行,
直到到达某个取消点(CancellationPoint)。取消点是线程检查是否被取消并按照请求进行动作的一个位置.

测试伪代码

#include <unistd.h>
#include <sys/types.h>
#include<sys/socket.h>
#include<netdb.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<errno.h>
#include<malloc.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<stdarg.h>
#include<fcntl.h>

static int socket_fd;

static void* pthread_func(void* arg)
{
    char buf[128] = {0};
    while(1){
        printf("read start \r\n");
        pthread_testcancel(); //阻塞时没有这行
        read(socket_fd, buf, 128);
        pthread_testcancel();//阻塞时没有这行
        printf("read end\r\n");
    }

    return NULL;
}

int main(int argc, char const *argv[]) {

    socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    
    pthread_t tid;
    pthread_create(&tid, NULL, pthread_func, NULL);

    sleep(2);
    printf("pthread_cancel tid[%d]\r\n", tid);
    int ret = pthread_cancel(tid);
    printf("ret[%d]\r\n", ret);
    pthread_join(tid, NULL);
    printf("pthread_join\r\n");
    close(socket_fd);
    socket_fd = -1;
    return 0;
}

非必现问题,必须实际环境测试, read要有接收
本地read无数据接收时无法复现问题!

原因

根据POSIX标准,pthread_join()、pthread_testcancel()、pthread_cond_wait()、pthread_cond_timedwait()、sem_wait()、sigwait()等函数以及
read()、write()等会引起阻塞的系统调用都是Cancelation-point,而其他pthread函数都不会引起Cancelation动作。
但是pthread_cancel的手册页声称,由于LinuxThread库与C库结合得不好,因而目前C库函数都不是Cancelation-point;但CANCEL信号会使线程从阻塞的系统调用中退出,并置EINTR错误码,因此可以在需要作为Cancelation-point的系统调用前后调用pthread_testcancel(),从而达到POSIX标准所要求的目标.
即如下代码段:
pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();

注意:
程序设计方面的考虑,如果线程处于无限循环中,且循环体内没有执行至取消点的必然路径,则线程无法由外部其他线程的取消请求而终止。因此在这样的循环体的必经路径上应该加入pthread_testcancel()调用.

真相大白:
pthread_cancel的手册页声称:LinuxThread库与C库结合得不好,C库函数都不是Cancelation-point, 需要作Cancelation-point的系统调用前后调用pthread_testcancel(),从而达到POSIX标准所要求的目标

参考

线程取消(pthread_cancel)


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处!
更多精彩内容,欢迎访问一只海星的主页

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值