From 73366743f8083ce835a783ab3faedfb7f6ed4398 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Mon, 2 Nov 2026 22:24:39 +0100 Subject: [PATCH 01/14] Fix GH-24787 delayed OOM during request startup --- main/main.c | 3 ++ .../gh24787_delayed_oom_request_startup.phpt | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/basic/gh24787_delayed_oom_request_startup.phpt diff --git a/main/main.c b/main/main.c index ee7d1cca69b5..03b9f2dafd3a 100644 --- a/main/main.c +++ b/main/main.c @@ -1922,6 +1922,9 @@ zend_result php_request_startup(void) /* PG(during_request_startup) = 0; */ php_hash_environment(); + if (ZEND_HAS_OOM()) { + zend_handle_delayed_oom(); + } zend_activate_modules(); PG(modules_activated)=1; } zend_catch { diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt new file mode 100644 index 000000000000..723bd5135b3b --- /dev/null +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -0,0 +1,38 @@ +--TEST-- +GH-24787 (Delayed OOM during request startup is handled as a fatal error) +--SKIPIF-- + +--FILE-- + 'GET', 'HTTP_COOKIE' => implode('; ', $cookies), 'SCRIPT_FILENAME' => $script, 'REDIRECT_STATUS' => '1'] +); +$output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]); +fclose($pipes[1]); +fclose($pipes[2]); +proc_close($process); +unlink($script); + +echo str_contains($output, 'Allowed memory size') ? "OOM handled\n" : $output; +?> +--EXPECT-- +OOM handled From 80dae4a3b820a4568f853596cc73c084548e84bb Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 18:38:18 +0100 Subject: [PATCH 02/14] Make delayed OOM startup test reproducible --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index 723bd5135b3b..44166c530f39 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -20,7 +20,7 @@ for ($i = 0; $i < 5000; $i++) { } $process = proc_open( - [getenv('TEST_PHP_CGI_EXECUTABLE'), '-n', '-d', 'memory_limit=8M', '-d', 'max_input_vars=10000', '-d', 'html_errors=0'], + [getenv('TEST_PHP_CGI_EXECUTABLE'), '-n', '-d', 'memory_limit=2M', '-d', 'max_input_vars=10000', '-d', 'html_errors=0'], [STDIN, ['pipe', 'w'], ['pipe', 'w']], $pipes, null, From e4431ac98bccc706d9b1f904e314457103db7c26 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 19:10:30 +0100 Subject: [PATCH 03/14] Keep delayed OOM test environment within Windows limits --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index 44166c530f39..04b6b0eeac32 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -16,7 +16,7 @@ file_put_contents($script, " Date: Wed, 11 Nov 2026 19:26:36 +0100 Subject: [PATCH 04/14] Keep delayed OOM test environment within Windows limits --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index 04b6b0eeac32..cf805fc1169c 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -15,7 +15,7 @@ $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " Date: Wed, 11 Nov 2026 19:30:09 +0100 Subject: [PATCH 05/14] Keep delayed OOM test environment within Windows limits --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index cf805fc1169c..c3b59afd8cbd 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -15,8 +15,8 @@ $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " 'GET', 'HTTP_COOKIE' => implode('; ', $cookies), 'SCRIPT_FILENAME' => $script, 'REDIRECT_STATUS' => '1'] + ['REQUEST_METHOD' => 'GET', 'HTTP_COOKIE' => implode(';', $cookies), 'SCRIPT_FILENAME' => $script, 'REDIRECT_STATUS' => '1'] ); $output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]); fclose($pipes[1]); From 9a723d42cc4373be1d3bf9d85e8f35ca911a0092 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 19:49:44 +0100 Subject: [PATCH 06/14] Keep delayed OOM test environment within Windows limits --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index c3b59afd8cbd..e4dbde5a7bde 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -15,8 +15,10 @@ $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " Date: Wed, 11 Nov 2026 19:50:06 +0100 Subject: [PATCH 07/14] Build nested cookie names literally --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index e4dbde5a7bde..10d39d333183 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -18,7 +18,7 @@ $cookies = []; for ($i = 0; $i < 2000; $i++) { $key = base_convert((string) $i, 10, 36); $value = $i < 1500 ? "xx" : "x"; - $cookies[] = "c$key[0][0][0]=$value"; + $cookies[] = 'c' . $key . '[0][0][0]=' . $value; } $process = proc_open( From 1b074a055f21eb1d0630dc745239c3e45b180cc9 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 20:16:28 +0100 Subject: [PATCH 08/14] Fit delayed OOM cookies within Windows environment limit --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index 10d39d333183..e22a8dcff635 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -14,11 +14,11 @@ if (!extension_loaded('uri')) { $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " Date: Wed, 11 Nov 2026 20:59:37 +0100 Subject: [PATCH 09/14] Keep delayed OOM test environment below Windows limit --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index e22a8dcff635..9518e41592bb 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -16,9 +16,9 @@ file_put_contents($script, " Date: Wed, 11 Nov 2026 22:03:50 +0100 Subject: [PATCH 10/14] Handle delayed OOM from RINIT failures --- Zend/zend_API.c | 4 ++ .../gh24787_delayed_oom_request_startup.phpt | 55 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 38f0c837a9fe..24120e61d7e4 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3458,6 +3458,10 @@ ZEND_API void zend_activate_modules(void) /* {{{ */ const zend_module_entry *module = *p; if (module->request_startup_func(module->type, module->module_number)==FAILURE) { + /* A delayed OOM may have caused the module startup failure. */ + if (ZEND_HAS_OOM()) { + zend_handle_delayed_oom(); + } zend_error(E_WARNING, "request_startup() for %s module failed", module->name); exit(1); } diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index 9518e41592bb..fb4961b3e213 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -14,27 +14,46 @@ if (!extension_loaded('uri')) { $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " 'POST', + 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', + 'CONTENT_LENGTH' => (string) strlen($body), + 'SCRIPT_FILENAME' => $script, + 'REDIRECT_STATUS' => '1', + ]; + $process = proc_open($command, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes, null, $environment); + fwrite($pipes[0], $body); + fclose($pipes[0]); + $output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); -$process = proc_open( - [getenv('TEST_PHP_CGI_EXECUTABLE'), '-n', '-d', 'memory_limit=2M', '-d', 'max_input_vars=10000', '-d', 'html_errors=0'], - [STDIN, ['pipe', 'w'], ['pipe', 'w']], - $pipes, - null, - ['REQUEST_METHOD' => 'GET', 'HTTP_COOKIE' => implode(';', $cookies), 'SCRIPT_FILENAME' => $script, 'REDIRECT_STATUS' => '1'] -); -$output = stream_get_contents($pipes[1]) . stream_get_contents($pipes[2]); -fclose($pipes[1]); -fclose($pipes[2]); -proc_close($process); + $rinitFailed = $rinitFailed || str_contains($output, 'request_startup()'); + $oomReported = $oomReported || str_contains($output, 'Allowed memory size'); +} unlink($script); -echo str_contains($output, 'Allowed memory size') ? "OOM handled\n" : $output; +echo !$rinitFailed && $oomReported ? "OOM handled\n" : "RINIT failure or no OOM reported\n"; ?> --EXPECT-- OOM handled From 77cdad8fc178d1e1c5ee3fd2ce822906de4758b6 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 22:14:36 +0100 Subject: [PATCH 11/14] Scan OOM test range across build variants --- tests/basic/gh24787_delayed_oom_request_startup.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/basic/gh24787_delayed_oom_request_startup.phpt b/tests/basic/gh24787_delayed_oom_request_startup.phpt index fb4961b3e213..710730762a7c 100644 --- a/tests/basic/gh24787_delayed_oom_request_startup.phpt +++ b/tests/basic/gh24787_delayed_oom_request_startup.phpt @@ -14,8 +14,8 @@ if (!extension_loaded('uri')) { $script = tempnam(sys_get_temp_dir(), 'gh24787'); file_put_contents($script, " Date: Wed, 11 Nov 2026 22:50:32 +0100 Subject: [PATCH 12/14] Use adaptive worker count in Linux test action --- .github/actions/test-linux/action.yml | 4 ---- .github/workflows/test-suite.yml | 1 - 2 files changed, 5 deletions(-) diff --git a/.github/actions/test-linux/action.yml b/.github/actions/test-linux/action.yml index e89c942d52e1..f304133a2b20 100644 --- a/.github/actions/test-linux/action.yml +++ b/.github/actions/test-linux/action.yml @@ -9,9 +9,6 @@ inputs: jitType: default: 'disable' required: false - idleCpu: - default: 'false' - required: false runs: using: composite steps: @@ -50,7 +47,6 @@ runs: -d opcache.jit=${{ inputs.jitType }} \ -d opcache.protect_memory=1 \ -d opcache.jit_buffer_size=64M \ - ${{ inputs.idleCpu == 'true' && '-j$(($(/usr/bin/nproc) - 1))' || '-j$(/usr/bin/nproc)' }} \ -g FAIL,BORK,LEAK,XLEAK \ --no-progress \ --offline \ diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index dcd61adf17c8..551e16f1b479 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -188,7 +188,6 @@ jobs: ${{ matrix.asan && '--asan' || '' }} ${{ matrix.repeat && '--repeat 2' || '' }} ${{ matrix.variation && '-d zend_test.observer.enabled=1 -d zend_test.observer.show_output=0' || '' }} - idleCpu: ${{ matrix.asan && 'true' || 'false' }} - name: Test Tracing JIT if: ${{ inputs.all_variations || matrix.asan }} uses: ./.github/actions/test-linux From cefbbe6a82a3c8132994c8b6402ba63c039d1161 Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Wed, 11 Nov 2026 23:26:04 +0100 Subject: [PATCH 13/14] Run i386 test suite outside container seccomp --- .github/actions/apt-x32/action.yml | 6 +++--- .github/actions/install-linux-x32/action.yml | 16 ++++++++-------- .github/workflows/test-suite.yml | 13 ++++++------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/.github/actions/apt-x32/action.yml b/.github/actions/apt-x32/action.yml index 14182e768795..0f27b88497ac 100644 --- a/.github/actions/apt-x32/action.yml +++ b/.github/actions/apt-x32/action.yml @@ -9,10 +9,10 @@ runs: OPCACHE_TLS_TESTS_DEPS="gcc clang lld" export DEBIAN_FRONTEND=noninteractive - dpkg --add-architecture i386 - apt-get update -y | true + sudo dpkg --add-architecture i386 + sudo env DEBIAN_FRONTEND=noninteractive apt-get update -y | true # TODO: Reenable postgresql + postgresql-contrib packages once they work again. - apt-get install -y \ + sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y \ autoconf \ bison \ curl \ diff --git a/.github/actions/install-linux-x32/action.yml b/.github/actions/install-linux-x32/action.yml index 4ef87ee03fd3..95d7fc738b1c 100644 --- a/.github/actions/install-linux-x32/action.yml +++ b/.github/actions/install-linux-x32/action.yml @@ -5,11 +5,11 @@ runs: - shell: bash run: | set -x - make install - mkdir -p /etc/php.d - chmod 777 /etc/php.d - echo mysqli.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/mysqli.ini - echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock > /etc/php.d/pdo_mysql.ini - echo opcache.enable_cli=1 >> /etc/php.d/opcache.ini - echo opcache.protect_memory=1 >> /etc/php.d/opcache.ini - echo opcache.preload_user=root >> /etc/php.d/opcache.ini + sudo make install + sudo mkdir -p /etc/php.d + sudo chmod 777 /etc/php.d + echo mysqli.default_socket=/var/run/mysqld/mysqld.sock | sudo tee /etc/php.d/mysqli.ini > /dev/null + echo pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock | sudo tee /etc/php.d/pdo_mysql.ini > /dev/null + echo opcache.enable_cli=1 | sudo tee /etc/php.d/opcache.ini > /dev/null + echo opcache.protect_memory=1 | sudo tee -a /etc/php.d/opcache.ini > /dev/null + echo opcache.preload_user=root | sudo tee -a /etc/php.d/opcache.ini > /dev/null diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 551e16f1b479..e72dd8ba74d0 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -229,15 +229,14 @@ jobs: fail-fast: false matrix: ${{ fromJson(inputs.branch).jobs.LINUX_X32.matrix }} name: "LINUX_X32_${{ matrix.debug && 'DEBUG' || 'RELEASE' }}_${{ matrix.zts && 'ZTS' || 'NTS' }}" - runs-on: ubuntu-latest + # The container seccomp profile blocks i386 socket syscalls used by the test suite. + runs-on: ubuntu-${{ fromJson(inputs.branch).config.ubuntu_version }} timeout-minutes: 180 - container: - image: ubuntu:${{ fromJson(inputs.branch).config.ubuntu_version }} env: - MYSQL_TEST_HOST: mysql - PDO_MYSQL_TEST_DSN: mysql:host=mysql;dbname=test - PDO_MYSQL_TEST_HOST: mysql - PDO_FIREBIRD_TEST_DSN: firebird:dbname=firebird:test.fdb + MYSQL_TEST_HOST: 127.0.0.1 + PDO_MYSQL_TEST_DSN: mysql:host=127.0.0.1;dbname=test + PDO_MYSQL_TEST_HOST: 127.0.0.1 + PDO_FIREBIRD_TEST_DSN: firebird:dbname=localhost:test.fdb services: mysql: image: mysql:8.4 From ea3c6a698e494e92c0e2bc215e2f6bf7ff93c25d Mon Sep 17 00:00:00 2001 From: Alessio Attilio Date: Thu, 12 Nov 2026 00:32:15 +0100 Subject: [PATCH 14/14] Clarify delayed OOM startup handling --- Zend/zend_API.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 24120e61d7e4..355b54bed88b 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3458,7 +3458,7 @@ ZEND_API void zend_activate_modules(void) /* {{{ */ const zend_module_entry *module = *p; if (module->request_startup_func(module->type, module->module_number)==FAILURE) { - /* A delayed OOM may have caused the module startup failure. */ + /* Surface a delayed OOM before reporting a generic module startup failure. */ if (ZEND_HAS_OOM()) { zend_handle_delayed_oom(); }