FPM: pools with different disable_functions sharing one opcache run scripts wrongly (var_export() calls var_dump(), SIGSEGV in the restricted pool) on 8.4/8.5/8.6
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 48/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Ativa
- Stack de tecnologia
- php
- Domínio
- backend, performance
Direção de pesquisa
Start by reproducing with the provided FPM configuration, scripts, and run.sh on PHP 8.5; compare pool request order and confirm that disabling OPcache or optimizer bits 0x20 and 0x40 avoids the issue. The report does not identify source files or tests, so trace the OPcache optimizer passes and how calls are resolved across pools. Done when shared OPcache preserves correct function dispatch for pools with different disable_functions settings, including the reported crash case.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Description
Quoted text written with an LLM and checked by a human developer.
Two pools in one FPM master, one with
php_admin_value[disable_functions]and one without, share the opcache. Once a script has been compiled and cached through one pool, the other pool executes it wrongly: an internal function call is dispatched to a different internal function, and a worker of the restricted pool can crash.
fpm.conf:
[global]
daemonize = no
error_log = /dev/stderr
[a]
user = nobody
listen = /tmp/a.sock
listen.owner = nobody
pm = static
pm.max_children = 1
php_admin_value[disable_functions] = exec
[b]
user = nobody
listen = /tmp/b.sock
listen.owner = nobody
pm = static
pm.max_children = 1
t.php:
<?php
echo var_export([1, 'x' => true], true), "\n";
Request
t.phpthrough poola, then through poolb(a ~20-line FastCGI client,fcgi.php, is attached below so that no web server is needed). Resulting output,php:8.5-fpm(8.5.12), default settings (opcache is built in):
pool a: array (
0 => 1,
'x' => true,
)
pool b: array(2) {
[0]=>
int(1)
["x"]=>
bool(true)
}
bool(true)
Pool
bprinted the output ofvar_dump()(and its return value) instead ofvar_export(). Expected output: the same text as poola. With the order reversed (bfirst, thena) poola, the one withexecdisabled, printsdebug_zval_dump()style output (array(2) interned {...}).
On Ubuntu's 8.5.4 (
8.5.4-0ubuntu1.5,-nwithzend_extension=opcache) poolbfails withconvert_uudecode() expects exactly 1 argument, 2 givenfor the same script, i.e. the call is dispatched to a third function.
A script that calls the disabled function itself (
t2.php:echo exec('echo hi');), requested throughbfirst and then througha, kills the worker of the restricted pool:
WARNING: [pool a] child 10 exited on signal 11 (SIGSEGV) after 2.015193 seconds from start
What I checked:
result 8.5.12, 8.4.27 (official php:*-fpmimages), 8.6.0RC4 (php:8.6-rc-fpm, ZTS), Ubuntu 8.5.4wrong function called 8.3.36 ( php:8.3-fpm)correct opcache.enable=0correct opcache.optimization_level=0correct 8.4 without zend_extension=opcache(-n)correct default opcache.optimization_levelwith the bit0x20or the bit0x40cleared (one at a time; every other bit alone makes no difference)correct two separate FPM masters, one pool each, same disable_functionssplit (8.5.12 and 8.4.27)correct, no cross-effect
I did not trace what exactly gets cached or resolved by index or by pointer, so I cannot say more than that the optimizer passes
0x20(DFA) and0x40(call graph) are both needed. I saw no case where a disabled function actually ran: the restricted pool crashed or printed the output of another function, but never executedexec. FPM acceptsphp_admin_value[disable_functions]per pool, so a setup like this is not exotic, and the symptom (wrong output rather than an error) is hard to diagnose; the workaround isopcache.enable=0, or one master per differingdisable_functionsset.
I found no open or closed report about this.Same root cause as GH-17733. Related but different: #21974 (SIGSEGV withdisable_functionsper pool, ZTS builds only) and #24047 (system id and frameless functions).
To reproduce (podman/docker; the directory holds
fpm.conf,t.php,t2.php,fcgi.php,run.sh):
docker run --rm -v "$PWD":/m docker.io/library/php:8.5-fpm sh /m/run.sh "a b a b" t.php
docker run --rm -v "$PWD":/m docker.io/library/php:8.5-fpm sh /m/run.sh "b a" t2.php
docker run --rm -v "$PWD":/m docker.io/library/php:8.5-fpm sh /m/run.sh "a b a b" t.php -d opcache.enable=0 # correct
control: one master per pool (correct on 8.5.12 and 8.4.27)
sed -n '1,10p' /m/fpm.conf > /tmp/fpm-a.conf
{ sed -n '1,3p' /m/fpm.conf; sed -n '11,16p' /m/fpm.conf; } > /tmp/fpm-b.conf
php-fpm -y /tmp/fpm-a.conf -F >/m/fpm-a.out 2>&1 &
php-fpm -y /tmp/fpm-b.conf -F >/m/fpm-b.out 2>&1 &
sleep 2
for p in a b a b b a; do printf -- "pool %s: " "$p"; php /m/fcgi.php /tmp/$p.sock /m/t.php 2>&1 | tr '\n' ' '; echo; done
fcgi.php:
<?php
// Minimal FastCGI GET client: php fcgi.php /tmp/a.sock /m/t.php
[$sock, $script] = [$argv[1], $argv[2]];
$rec = fn(int $t, string $b) => pack('CCnnCx', 1, $t, 1, strlen($b), 0) . $b;
$kv = function (string $k, string $v): string {
$l = fn(int $n) => $n < 128 ? chr($n) : pack('N', $n | 0x80000000);
return $l(strlen($k)) . $l(strlen($v)) . $k . $v;
};
$p = $kv('SCRIPT_FILENAME', $script) . $kv('REQUEST_METHOD', 'GET') . $kv('SCRIPT_NAME', '/t.php')
. $kv('SERVER_PROTOCOL', 'HTTP/1.1') . $kv('REQUEST_URI', '/t.php') . $kv('QUERY_STRING', '');
$s = stream_socket_client("unix://$sock", $en, $es, 10);
fwrite($s, $rec(1, pack('nCx5', 1, 0)) . $rec(4, $p) . $rec(4, '') . $rec(5, ''));
$out = '';
while (!feof($s)) {
$h = stream_get_contents($s, 8);
if (strlen($h) < 8) break;
$d = unpack('Cv/Ct/nid/nlen/Cpad', $h);
$body = $d['len'] + $d['pad'] ? stream_get_contents($s, $d['len'] + $d['pad']) : '';
if ($d['t'] === 6 || $d['t'] === 7) $out .= substr($body, 0, $d['len']);
if ($d['t'] === 3) break;
}
echo preg_replace('~^.*?\r\n\r\n~s', '', $out) ?: "(empty response / connection reset)\n";
run.sh:
ord=$1; scr=$2; shift 2
php -v | head -1
php-fpm "$@" -y /m/fpm.conf -F >/m/fpm.out 2>&1 &
sleep 2
for p in $ord; do printf -- "pool %s: " "$p"; php /m/fcgi.php /tmp/$p.sock /m/$scr 2>&1 | tr '\n' ' '; echo; done
grep -E "SIGSEGV|signal" /m/fpm.out
PHP Version
PHP 8.5.12 (cli) (built: Oct 21 2026 15:49:51) (NTS) [php:8.5-fpm]
PHP 8.4.27 (cli) (built: Oct 21 2026 15:53:31) (NTS) [php:8.4-fpm, opcache loaded]
PHP 8.6.0RC4 (cli) (built: Oct 21 2026 22:05:36) (ZTS) [php:8.6-rc-fpm]
PHP 8.5.4-0ubuntu1.5 (Ubuntu 26.04)
Operating System
Debian (official Docker images), Ubuntu 26.04
- Linguagem predominante
- C
- Estrelas
- 41.8k
- Forks
- 8.5k
- Merge médio
- 2d 13h
- PRs com merge (30d)
- 145
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de php/php-src
-
ext/openssl: 8.2.31+/8.3.31+ fail to build against OpenSSL 1.0.2 (ASN1_STRING_get0_data in xp_ssl.c)Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 79/100
Mantenedores costumam responder em até 1 dia
-
Bug Status: Needs Triage
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100
php/php-src#25397 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
SNMP accepts malformed remote portsTalvez já em andamento Um pull request vinculado a esta issue está aberto ou já foi mesclado. Aberta
Dificuldade 2/5 Meio dia Facilidade para iniciantes 62/100
php/php-src#25137 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Bug Status: Needs Triage
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 64/100
Mantenedores costumam responder em até 1 dia
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFFTalvez já em andamento Um pull request vinculado a esta issue está aberto ou já foi mesclado. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
Mantenedores costumam responder em até 1 dia
Todas as issues de php/php-src
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
-
not for AI lovers
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
OSGeo/gdal#15515 · 1 comentário ·
Mantenedores costumam responder em até 1 dia
-
Template: Bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 83/100
betaflight/betaflight#16014 ·
Mantenedores costumam responder em até 3 dias
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 75/100
ly05010419/MacNativeGames#2119 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100