我有一台 CentOS VM,上面运行着一个 php 套接字服务器,该服务器在每个连接上都会分叉。子进程完成其工作然后退出。
父进程也在等待收割死去的僵尸进程(我已经检查了ps auxf
输出)
pcntl_wait($status, WNOHANG);
在每次 fork 之后执行,以便清理 1 个僵尸进程(如果有)
然而,经过长时间运行后,父节点无法分叉。
我认为这是因为32768
限制。输出中的进程数ps -auxf
始终在 750 左右。
[root@test-machine ~]# cat /proc/self/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 119925 119925 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 119925 119925 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
[root@test-machine ~]# cat /proc/sys/kernel/pid_max
32768
更新:
我检查了日志,发现错误信息如下PHP Fatal error: Maximum execution time of 30 seconds exceeded in myfile.php
它指向的行是pcntl_wait($status, WNOHANG);
,用于等待子进程终止。WNOHANG
标志确保它不会挂起,因此如果没有退出的子进程,它将继续执行。
虽然“最大时间”可以更改,但有些东西会导致pcntl_wait
循环。我认为操作系统上的某些东西导致了这种情况的发生。这是具有最大连接的套接字(我有多个套接字,只有这个受到影响)
答案1
我检查了函数 prcntl_wait 的 PHP 文档并发现了这一点:
选项
如果您的系统(主要是 BSD 风格的系统)上可以使用 wait3,则可以提供可选的 options 参数。如果未提供此参数,则 wait 将用于系统调用。如果 wait3 不可用,则提供 options 的值将不起作用。options 的值是以下两个常量中的零个或多个的值,并进行 OR 运算:
可能是您的操作系统没有 wait3,这导致了这个问题。也许您可以更改功能,pcntl_waitpid
这样就可以解决您的问题。