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
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- php
- Área
- backend, performance
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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
- Lenguaje dominante
- C
- Estrellas
- 41.8k
- Forks
- 8.5k
- Merge medio
- 2 d 13 h
- PR fusionados (30 d)
- 145
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más 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)Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
Los mantenedores suelen responder en 1 día
-
Bug Status: Needs Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
php/php-src#25397 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
SNMP accepts malformed remote portsPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 Medio día Aptitud para principiantes 62/100
php/php-src#25137 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Bug Status: Needs Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
Los mantenedores suelen responder en 1 día
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFFPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 1 día
Todos los issues de php/php-src
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
-
not for AI lovers
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
OSGeo/gdal#15515 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Template: Bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
betaflight/betaflight#16014 ·
Los mantenedores suelen responder en 3 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 75/100
ly05010419/MacNativeGames#2119 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100