sem_init重复调用引发sem_wait线程无法被唤醒
问题
一段老代码,两个线程,一个线程调用sem_wait等待信号量,另外一个线程在某失败分支会调用sem_init清信号量,结果导致sem_wait线程无法被唤醒;
分析
Linux manpage
从描述中可见,初始化一个已经被初始化的信号量会导致未定义行为;
NAME
sem_init - initialize an unnamed semaphore SYNOPSIS
#include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value); Link with -lrt or -pthread. DESCRIPTION
... Initializing a semaphore that has already been initialized results in undefined behavior.
glibc源码
到底会发生什么未定义行为,我们直接看源码吧;
首先,对比结构体,旧结构体只有value成员,新结构体中增加了private和nwaiters成员;nwaiters成员会在调用sem_wait时候增加;
然后,对比sem_post唤醒函数;可见,新唤醒函数会在唤醒操作执行之前对nwaiters进行判断,只有当nwaiters>0时,才进行唤醒;
而旧的唤醒操作,则没有类似判断;
现在,我们清楚了,老代码用的老版本的glibc,内部没有等待判断,一直没有出问题,而使用新版本的glibc之后,加入了判断,就有问题了;
结论
- sem_init是用来在初始化的时候调用初始化信号量的,并不是用来将信号量清零的;
- 重复调用sem_init的行为可能导致已经处于sem_wait的线程无法被唤醒;
- 旧版本的glibc机制比较弱,所以老代码一直运行很好;但是新glibc作了检查,所以会出问题;
- 按照目前代码看,如果单个线程自己在调用了sem_wait之后再调用sem_init时没什么影响的;但是不保证以后的glibc会再做什么修改造成影响;
- 除了初始化阶段,其他流程中不要使用sem_init;
- 最好使用其他方式替代信号量,比如条件变量;
sem_init重复调用引发sem_wait线程无法被唤醒的更多相关文章
- Python threading 单线程 timer重复调用函数
项目中需要使用定时器,每次都使用构造器函数调用: timer = threading.Timer(timerFlag, upload_position) timer.start() 打印线程后发现,每 ...
- Fragmen横竖屏切换,导致页面混乱,oncreateView重复调用
在清单文件Activity设置属性 android:screenOrientation="landscape" android:configChanges="screen ...
- Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...
- 关于ListView中getView被重复调用的问题
我用ListView显示数据时,自定义了一个适配器(extends ArrayAdapter),然后重写了getView方法,现在出现一个问题,就是这个getView()方法被重复调用了,比如我的_d ...
- Unity延迟和重复调用方法
延迟调用方法 Invoke(arg1,arg2) arg1 是延迟调用的字符串方法名,arg2是延迟多少时间调用arg1 方法. 重复调用方法 InvokeRepeating(arg1,arg2,ar ...
- 解决FTPClient linux环境下FTPClient调用retrieveFileStream导致线程挂起(防火墙问题);下载文件小于实际文件问题
FTPClient调用retrieveFileStream导致线程挂起(防火墙问题):下载文件小于实际文件问题解决 实际是因为FTP的两种传输模式:主动模式和被动模式的不同而导致的 FTPClient ...
- Android ListView getView()方法重复调用导致position错位
问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...
- FeignClient spi 调用 短路异常 & 线程池配置
FeignClient spi 调用 短路异常 & 线程池配置 默认配置见:HystrixThreadPoolProperties 线程池对象:com.netflix.hystrix.Hyst ...
- JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)
一.前言 在多线程的场景下,我们会经常使用加锁,来保证线程安全.如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题.也可以使用Condition的awai ...
随机推荐
- live555的使用(转载)
Live555 是一个为流媒体提供解决方案的跨平台的C++开源项目,它实现了对标准流媒体传输协议如RTP/RTCP.RTSP.SIP等的支持.Live555实现 了对多种音视频编码格式的音视频数据的流 ...
- html()方法与append()方法
注意加#!!!!!! $("#valuess").html("<input type='text' name='name' value= " + valu ...
- table标签修改tr,td标签的行距
修改tr标签的行距,tbale标签的td标签间距 看如下Css文件的代码,其都没有table的tr行距产生效果 tr{ margin-top: 10px; padding: 10px; } td{ m ...
- Flink原理(二)——资源
前言 本文主要是想简要说明Flink在集群部署.任务提交.任务运行过程中资源情况,若表述有误欢迎大伙留言分享,非常感谢! 一.集群部署阶段 集群部署这里指的是Flink standalone模式,因为 ...
- 资源管理与调度系统-资源管理系统Mesos
资源管理与调度系统-资源管理系统Mesos 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Mesos是诞生于UC Berkeley的一个研究项目,它的设计动机是解决编程模型和计算框 ...
- homebrew一直处于updating状态
vim ~/.bash_profile 增加一行 export HOMEBREW_NO_AUTO_UPDATE=true 之后再source一下
- yolov3---报"段错误"的可能原因及解决方法
参考: ************************************************************************************************ ...
- 云计算/云存储---Ceph和Openstack的cinder模块对接方法
1.创建存储池 在ceph节点中执行如下语句. #ceph osd pool create volumes 2.配置 OPENSTACK 的 CEPH 客户端 在ceph节点两次执行如下语句,两次{y ...
- PL/sql配置相关
可以安装oracle之后,打开PL/sql之后,自动找到oracle的路径以及数据库连接. 或者:安装oracle客户端,手动在PL/sql中配置oic以及oracle主目录的位置,并且配置好C: ...
- es6 let介绍及应用场景
关于更多es6建议去看阮一峰的博客~ es6入门:http://es6.ruanyifeng.com/ 源码仓库:https://github.com/ruanyf/es6tutorial let介绍 ...