菜单

Linux信号处理函数可重入问题

2017年9月6日 - Linux, 程序设计

之前我们的服务程序用到了定时器,最近偶然发现定时器处理函数在执行没完时又一个定时器信号到了。在定时器处理函数中,我们打印了一些信息,打印使用的是某个开源库,这个库在打印时用到了锁功能,Linux下的锁(Mutex)默认是非递归的,也就是一个线程如果已经获得了锁,就不能再次获取到该锁。这样导致的结果是第一次进入定时器处理函数获得锁后,释放之前又一次进入该函数,这时候尝试获取锁失败使得线程在当前位置等待锁,又过了一会第三个定时器信号到达,同样进入处理函数试图取得锁,因为第一次进入获取到了锁而且没有释放,后续的获取锁操作都不会成功,因为定时器处理函数在同一个线程里执行,所以第一次获取到锁后就没法继续执行也就没法释放了,于是产生死锁导致进程崩溃。

信号处理函数属于可重入函数,即在自身没有执行完毕时可以被同一个信号中断,于是又一次进入该函数,因此对于可重入函数,一般

  1. 最好不要执行复杂而耗时的任务;
  2. 不要使用全局变量;
  3. 不要返回指向全局变量的指针;
  4. 如果需要使用全局变量,则先拷贝到局部变量后再使用;
  5. 不要使用不可递归锁甚至最好不用锁;
  6. 不要调用不可重入函数如malloc,调用不可重入函数则该函数自身也变成了不可重入函数。

还记得很久以前在看Linux内核开发资料时,也有“中断处理函数尽可能少做事情”的忠告,时隔多年,还是掉坑里了。

发表评论