在 PHP 8.2 中创建 unix 套接字的副作用是什么?

问题描述 投票:0回答:1

在我们众多 PHP pod 中的两个(我们在 Kubernetes 下运行)中,我们遇到了 Unix 套接字泄漏问题。我们的 PHP CLI 进程似乎正在打开但没有关闭许多 unix 套接字,直到在一个不相关的位置 PHP 崩溃并显示

PHP Warning: stream_select(): You MUST recompile PHP with a larger value of FD_SETSIZE.

我们的其他 Pod 也打开了一些 UNIX 套接字,但数量很少,所以这不是问题。

令人困惑的是我们没有使用 UNIX 套接字来做任何事情。与其他进程的所有通信均纯粹通过 TCP/IP。所有插座均为:

  • 处于
    ESTABLISHED
    状态
  • ss -x
    表示这些套接字上没有发送或接收数据
  • 他们在文件系统中没有文件
  • netstat
    表示他们都有
    RefCount
    3
    ,如果这意味着什么的话
  • ss -xp
    还表明,每个套接字的两端都由同一个(且唯一)PHP 进程持有。

因此...由于某种原因,PHP 程序正在创建 UNIX 套接字,将它们保持打开状态,并抓住该套接字的两端(两个不同的文件描述符),并且不让它们离开。

此外,代码中没有调用

stream_socket_pair
socket_create_pair

我从中收集到的是,这些套接字是作为我正在使用的其他一些 PHP 内置函数的副作用而创建的。 CURL 是这里的主要嫌疑人,但它也在其他 Pod 中大量使用,没有出现问题。事实上,我想不出这两个 pod 正在做而其他 pod 没有做的任何事情。

哪些内置 PHP 函数(包括默认与 PHP 捆绑在一起的扩展中的函数)可能会导致无意中创建 UNIX 套接字对?

补充:

ss -xp
看起来像:

# ss -xp
Netid               State               Recv-Q               Send-Q                             Local Address:Port                                  Peer Address:Port                   Process
u_str               ESTAB               0                    0                                              * 481304571                                        * 481304572               users:(("php",pid=7,fd=494))
u_str               ESTAB               0                    0                                              * 480934363                                        * 480934362               users:(("php",pid=7,fd=289))
u_str               ESTAB               0                    0                                              * 480899260                                        * 480899259               users:(("php",pid=7,fd=255))
u_str               ESTAB               0                    0                                              * 480853228                                        * 480853229               users:(("php",pid=7,fd=207))
u_str               ESTAB               0                    0                                              * 478659551                                        * 478659550               users:(("php",pid=7,fd=82))
u_str               ESTAB               0                    0                                              * 481263776                                        * 481263775               users:(("php",pid=7,fd=484))
u_str               ESTAB               0                    0                                              * 481014545                                        * 481014546               users:(("php",pid=7,fd=339))
u_str               ESTAB               0                    0                                              * 480847844                                        * 480847845               users:(("php",pid=7,fd=221))
u_str               ESTAB               0                    0                                              * 479446282                                        * 479446283               users:(("php",pid=7,fd=185))
u_str               ESTAB               0                    0                                              * 479430966                                        * 479430965               users:(("php",pid=7,fd=162))
u_str               ESTAB               0                    0                                              * 481391710                                        * 481391711               users:(("php",pid=7,fd=515))
u_str               ESTAB               0                    0                                              * 481013994                                        * 481013995               users:(("php",pid=7,fd=352))
u_str               ESTAB               0                    0                                              * 480884372                                        * 480884373               users:(("php",pid=7,fd=233))
.... many, may more lines ...
php unix-socket resource-leak connection-leaks
1个回答
0
投票

我自己找到了答案。在这里发帖是为了帮助接下来的人。罪魁祸首是... *鼓声*... CURL。特别是,PHP 8.2 中的

curl_multi_init()
打开一对 UNIX 套接字,可能是为了某种跨线程同步。

这是重现它的一段代码:

$handles = [];

for ( $i = 0; $i < 10; $i++ )
    $handles[] = curl_multi_init();

echo "Sleeping...";
sleep(10); // Here we have 20 unix sockets open

foreach ($handles as $h)
    curl_multi_close($h); // According to PHP docs, this doesn't do anything in PHP 8, but it's good style anyway.

$handles = [];
echo "Sleeping again...";
sleep(10); // Here we have 2 unix sockets open... because the $h variable still holds the last handle

echo "Goodbye!";

我不知道为什么我的本地计算机上没有出现此行为。可能和具体的CURL或者PHP版本有关系。特别是:

我有 PHP 8.2.13 和 CURL 8.5.0(这没有问题),而 Kubernetes pod 有 PHP 8.2.16 和 CURL 7.88.1(这有问题)。

如果有人知道为什么我的机器上没有发生这种情况,请告诉我!

好吧,现在只是为了追查我自己的

CurlMultiHandle
漏洞 - 这是一项更容易管理的任务,超出了这个问题的范围。

© www.soinside.com 2019 - 2024. All rights reserved.