pthread_cancel引起的死锁_huanzai2的专栏-程序员宅基地

技术标签: 线程  thread  网络模型  pthread_cancel  

最近发现程序无法终止,查证发现问题出现在pthread_cancel上。加锁代码如下:

IAidTaskPtr CAidThreadPool::getTask() {
	IAidTaskPtr pTask = NULL;
	while (m_bRun)
	{
		pTask = NULL;
		{
			CAutoLock lock(m_BusinessLock);
			if ( m_listTasks.empty() )
			{
				m_BusinessLock.wait();// pthread_cond_wait()实现
				continue;
			}

			if (!m_listTasks.empty()) {
				pTask = m_listTasks.front();
				m_listTasks.pop_front();
				break;
			}
		}
	}

	return pTask;
}


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

pthread_cancel manual 说以下几个 POSIX 线程函数是取消点:

pthread_join(3)

pthread_cond_wait(3)

pthread_cond_timedwait(3)

pthread_testcancel(3)

sem_wait(3)

sigwait(3)

而当pthread_cancel时,程序正好处于pthread_cond_wait这个取消点上,但为什么还是发生了死锁呢?

在Linux的实现中在真正wait之前,有这样一段代码:

/* Before we block we enable cancellation. Therefore we have to install a cancellation handler. */
__pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);

而__condvar_cleanup,做了什么事情呢?

/* Get the mutex before returning unless asynchronous cancellation is in effect. */
__pthread_mutex_cond_lock (cbuffer->mutex);
}
加上了锁,而这段代码是在pthread_cancel发生时会执行到,这也就直接导致了死锁。

解决:不使用pthread_cancel终止线程


其他解决办法:

void cleanup(void *arg)
{
    pthread_mutex_unlock(&mutex);
}
void* thread0(void* arg)
{
    pthread_cleanup_push(cleanup, NULL); // thread cleanup handler
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&cond, &mutex);
    pthread_mutex_unlock(&mutex);
    pthread_cleanup_pop(0);
    pthread_exit(NULL);
}


参考文献:

http://www.linuxalgorithm.com/1086654/

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/huanzai2/article/details/39206211

智能推荐

计算机网络第一二三章计算题,自考《计算机网络》第2章自测题_2022考研狗的博客-程序员宅基地

计算机网络第二章自测题一 填空题1.物理层的功能是实现原始数据在_______上的传输,它是数据通信的基础功能,实际的比特传输,是指在_______之上为上一个传输原始比特流的_______.2.数据通信的几个主要指标有_______、_______、_______、_______.3.物理层接口协议,实际上是DTE和DCE或其它通信设备之间的一组协定,其中DTE是指_______设备,属于用户所...

Linux命令--根据进程名杀死进程_IT利刃出鞘的博客-程序员宅基地_linux通过进程名杀死进程

原文网址:简介法1:ps + grep等用法ps -ef | grep procedure_name | grep -v grep | awk '{print $2}' | xargs kill -9procedure_name为进程名。分析ps -ef 列出所有进程 grep procedure_name 查找指定进程名的进程 awk '{print $2}' 筛选出进程的ID xargs kill 杀死指定进程 法2:killall用法

java 垃圾回收机制_Java的垃圾回收机制_御道御小黑的博客-程序员宅基地

前言在C++语言中, 程序员必须小心谨慎的处理每一项内存分配, 且内存使用完后必须手动释放曾经占用的内存空间。当内存释放不够完全时, 即存在分配但永不释放的内存块, 就会引起"内存泄漏"问题。而在Java语言中, 它给了程序员一个美好的承诺: 程序员无需管理内存, 因为JVM会有GC去自动进行垃圾回收。其实不然:垃圾回收并不会按照程序员的要求, 随时进行GC。垃圾回收并不会及时的清理内存, 尽管有...

数论概论读书笔记 36.高斯整数与唯一因子分解_Feynman1999的博客-程序员宅基地

高斯整数与唯一因子分解稍微偏了点理论,数域的扩展,这里不详细记录了主要是:高斯整数的唯一分解高斯整数带余除法高斯整数公因数性质高斯素数整除性质勒让德两平方数之和定理D1−D3D1−D3D_1-D_3差定理...

SpringBoot项目中使用.jsp作为页面_懵懵懂懂程序员的博客-程序员宅基地_springboot使用jsp页面

SpringBoot项目中使用.jsp作为页面SpringBoot 不建议使用jsp,会出现很多问题, 但是在做项目的时候可能还需要使用jsp。如果使用idea有的时候不能访问webapp目录,因此下边的jsp也就是不能被访问到了,出现404错误。如果是单独的一个项目是没有问题,按照如下修改就行了。1. 引入依赖pom.xml<!-- JSTL JSP 标准标签库 -->&l...

企业cc邮箱发件服务器设置,C#发送邮件(阿里企业邮箱示例 包括各个类型的服务器及端口配置)..._weixin_28795271的博客-程序员宅基地

本文讲解通过C#来实现发送邮件:1.我这里是使用的阿里企业邮箱,至于其他的163和QQ邮箱,就是修改下服务器地址和端口的问题2.至于发送失败的问题,在排除代码问题之后,可以看下自己使用的发送邮箱的账户是否开启了授权,特别是163和QQ邮箱,要开授权的这里针对阿里企业邮箱的各个服务器和端口配置说明一下:1.POP服务器:地址:pop3.mxhichina.com端口:110加密端口:9952.IMA...

随便推点

vs2008 C++项目连接mysql数据库详解_龙少爷_阿呆的博客-程序员宅基地_vs配置动态链接库

这两天由于写程序需要,须将c++程序中的数据存储在mysql数据库中,因此在网上各种找资料,终于弄清楚了整个流程。今天抽出点时间整理,方便自己,同时和各位分享。有错误的地方,请积极批评指正!第一步:安装MySQL5.5(下载地址:http://dev.mysql.com/downloads/mysql/)这里给出安装MySQL5.1的流程图解,5.5安装类似。一、MySQL5.1安装

java可以 javac_为什么在cmd中java可以运行,javac不行?_胡厨厨的博客-程序员宅基地

该楼层疑似违规已被系统折叠隐藏此楼查看此楼Path: C:\Program Files\NVIDIA Corporation\PhysX\Common;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program File...

Prometheus容器化部署_天外来物_的博客-程序员宅基地_prometheus容器化部署

Prometheus容器化部署环境容器化部署prometheus部署node_exporter添加节点到prometheus中部署grafana画图工具环境主机名IP地址服务prometheus192.168.237.137prometheus、grafananode-exporter192.168.237.131node_exporter容器化部署prometheus1、安装docker[[email protected] ~]# docker version

string字符串的常用属性_weixin_44389268的博客-程序员宅基地

找到这个字符串中每个字符出现了多少次 var str2 = "wha"; var obj = {}; str = str.toLowerCase(); for( var i = 0 ; i < str2.length; i++){ if(obj[str2[i]]){ obj[str2[i]]++; ...

时间工具类(全)_一名落魄的程序员的博客-程序员宅基地

获取两个日期之间的所有日期获取某年某月按天切片日期集合(某个月间隔多少天的日期集合)获取某年某月到某年某月按天的切片日期集合(间隔天数的集合)返回某个日期前几天的日期返回某个日期下几天的日期返回某月该季度的第一个月获取两个日期中的最小日期获取两个日期中的最大日期两个日期相减得到的毫秒数两个日期相减得到的天数获取本月是哪一月获取今年是哪一年获取某个日期的结束时间获取某个日期的开始时间获取本年的结束时间获取本年的开始时间获取某年的结束时间 如2021-12-31 23:59:59

微专业 Python精进路线展望 第一周_五月的霾的博客-程序员宅基地

上下文Context:程序执行中某个状态程序执行所需的一些内外部参数,构成了程序运行时的状态。上下文是用来表达程序运行状态的概念,对应内存状态。上下文是程序中断保留或恢复运行的重要状态信息。上下文管理器:一个可以在程序中加载独立上下文的对象万物皆对象:上下文管理器也是一个对象,管理者一个独立上下文区域。上下文管理器使用with显示创建。进入和退出分别对应__enter__()和...

推荐文章

热门文章

相关标签