一段废话
之前的shell分享中提到过strace这个流弊的工具,当时也是用linux C的代码造了一个场景来演示,而今再使用php构造一个场景来演示下如何查找一些坑,尽管差异不是很大
问题
先看下问题,最后会描述下构造的问题,问题如下
[root@c488ca153abc xiaoju]# php7/bin/php strace.php &
执行了一个php脚本,没有按照预期时间内返回,目测是阻塞住了
查问题
首先查pid
[root@c488ca153abc xiaoju]# ps aux | grep strace.php
root 12052 0.0 0.0 222344 10816 pts/0 S 18:15 0:00 php7/bin/php strace.php
通过strace看下12052进程的系统调用的阻塞情况
[root@c488ca153abc ~]# strace -p 12052
Process 12052 attached
wait4(-1,
可以看到当前阻塞在wait4,该系统调用会挂起当前进程,等待指定的子进程状态改变,其中参数是-1表示等待任一子进程的返回,如此我们去查看下12052下面的子进程
[root@c488ca153abc ~]# pstree -p 12052
php(12052)───php(12053)
继续使用strace看看12503为什么死也不返回
[root@c488ca153abc ~]# strace -p 12053
Process 12053 attached
flock(3, LOCK_EX
好吧,是flock文件锁,还是排他锁,文件描述符是3,看下对应的文件名是啥
可以通过lsof看,也可以通过/proc/12053/fd目录查看,该文件包含进程打开文件的情况
[root@c488ca153abc fd]# ll
总用量 0
lrwx------ 1 root root 64 11月 21 18:16 0 -> /dev/pts/0
lrwx------ 1 root root 64 11月 21 18:16 1 -> /dev/pts/0
lrwx------ 1 root root 64 11月 21 18:16 2 -> /dev/pts/0
lrwx------ 1 root root 64 11月 21 18:16 3 -> /home/xiaoju/lock
lrwx------ 1 root root 64 11月 21 18:16 5 -> socket:[2333709193]
倒数第三列就是文件描述符,3 -> /home/xiaoju/lock,找到12053心心念念的文件了,看下是谁占用了这个文件
[root@c488ca153abc fd]# lsof /home/xiaoju/lock | grep -v 12053
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php 12052 root 3uW REG 253,6 0 17725454 /home/xiaoju/lock
至此,可以断定是一个'死锁'了,父进程锁着文件等待子进程返回,子进程一直在等待父进程释放文件锁,如果还要进一步确定,可以到/proc/12052/目录中看到更多详细的信息,这里不赘述.
构造问题
构造了一个如下的问题,使用pcntl_fork建立一个父子进程,父子进程同时打开一个文件(内核级别会是两个不同的句柄),父进程先锁住A文件,然后开始pcntl_wait等待子进程的返回,最后释放锁,子进程以阻塞模式去获取文件锁,造成一个双等待的阻塞,如下是php的代码