程序运行多次后发生信号量访问失败
工作过程中遇到一个比较奇特的bug,在这里记录一下。
问题表现
原先有一部分程序能够正常运行,但是运行了几次错误的程序(会非正常退出,比如因为段错误等原因)之后,原先能够正常运行的程序就没法正常运行了,报错显示在获取信号量的过程中出错了,进一步导致了应用初始化的过程失败。但是在重启后这个问题又会解决(遇事不决,重启一下哈哈哈)
猜测原因
一开始怀疑是多线程访问信号量导致,但是这为什么会导致之前有效的程序失效呢?而且重启之后应该也没法解决这个问题。思考无果之后选择换一个思路。错误程序的代码中在非正常退出之前会执行一个申请信号量的操作,但是在段错误发生之后才会执行释放信号量的操作,那么有没有可能是信号量没有释放导致的?
检查
使用以下指令,查看一下系统当前的信号量(目前是能正常跑的)
ipcs -s
也可以加上wc -l直接统计一下数量即可
ipcs -s | wc -l
发现居然有60+个信号量集。查阅资料发现可以通过以下指令查看系统最大信号量集的数量,发现只有128
cat /proc/sys/kernel/sem
尝试执行一次会发生段错误的部分代码,发现信号量在进程结束后增加了6个,并且不会减少。
查阅资料发现,因为代码中创建的是非匿名信号量,在进程结束之后,如果没有主动将其释放,该信号量也不会自动的被操作系统释放,因为操作系统也不知道它到底会不会被其他的进程所使用。当信号量达到限制数量限制之后,就没法正常的申请新的信号量,导致程序运行失败(未验证)
解决方案
注册信号处理函数,在程序非正常退出时执行释放信号量的操作即可。

浙公网安备 33010602011771号