1--TEST-- 2FPM: Set CLOEXEC on the listen and connection socket 3--SKIPIF-- 4<?php 5require_once "skipif.inc"; 6FPM\Tester::skipIfShellCommandFails('lsof -v', 'lsof-org/lsof'); 7?> 8--FILE-- 9<?php 10 11require_once "tester.inc"; 12 13$cfg = <<<'EOT' 14[global] 15error_log = {{FILE:LOG}} 16[unconfined] 17listen = {{ADDR}} 18pm = static 19pm.max_children = 1 20pm.status_listen = {{ADDR[status]}} 21pm.status_path = /status 22env[PATH] = $PATH 23EOT; 24 25$code = <<<'EOT' 26<?php 27 28$fpmPort = $_GET['fpm_port']; 29 30echo "My sockets (expect to see 2 of them - one ESTABLISHED and one LISTEN):\n"; 31 32$mypid = getmypid(); 33$ph = popen("/bin/sh -c 'lsof -Pn -p$mypid' 2>&1 | grep TCP | grep '127.0.0.1:$fpmPort'", 'r'); 34echo stream_get_contents($ph); 35pclose($ph); 36 37echo "\n"; 38 39/* 40We expect that both LISTEN (inherited from the master process) and ACCEPTED (ESTABLISHED) 41have F_CLOEXEC and should not appear in the created process. 42 43We grep out sockets from non-FPM port, because they may appear in the environment, 44e.g. PHP-FPM can inherit them from the test-runner. We cannot control the runner, 45but we can test how the FPM behaves. 46*/ 47 48echo "Sockets after exec(), expected to be empty:\n"; 49$ph = popen("/bin/sh -c 'lsof -Pn -p\$\$' 2>&1 | grep TCP | grep '127.0.0.1:$fpmPort'", 'r'); 50var_dump(stream_get_contents($ph)); 51pclose($ph); 52 53EOT; 54 55$tester = new FPM\Tester($cfg, $code); 56$tester->start(); 57$tester->expectLogStartNotices(); 58$tester->request(query: 'fpm_port='.$tester->getPort())->printBody(); 59$tester->terminate(); 60$tester->expectLogTerminatingNotices(); 61$tester->close(); 62 63?> 64Done 65--EXPECTF-- 66My sockets (expect to see 2 of them - one ESTABLISHED and one LISTEN): 67%S 127.0.0.1:%d->127.0.0.1:%d (ESTABLISHED) 68%S 127.0.0.1:%d (LISTEN) 69 70Sockets after exec(), expected to be empty: 71string(0) "" 72Done 73--CLEAN-- 74<?php 75require_once "tester.inc"; 76FPM\Tester::clean(); 77?> 78