Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ PHP NEWS
- FPM:
. Fixed bug GH-24229 (fcgi_close() passes shutdown() a literal 1, which is
SHUT_RD in WASI). (Ryosuke Ishibashi)
. Fixed bug GH-21974 (Crash on worker shutdown in ZTS builds when
disable_functions is set in a pool configuration). (Sree24-ui)

- Fileinfo:
. Fixed bug GH-24289 (finfo::file() reports the wrong argument number for
Expand Down
20 changes: 20 additions & 0 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -3660,6 +3660,26 @@ static void zend_disable_function(const char *function_name, size_t function_nam
zend_error(E_WARNING, "Cannot disable function %s()", function_name);
return;
}
#ifdef ZTS
/* After zend_post_startup() the function table of a thread borrows the
* functions of the global function table, which destroys them on shutdown
* (see compiler_globals_ctor()). Remove them without destroying them. */
HashTable *function_table = CG(function_table);
zval *zv = zend_hash_str_find(function_table, function_name, function_name_length);
if (zv && (uint32_t) ((Bucket *) zv - function_table->arData) < CG(copied_functions_count)) {
dtor_func_t dtor = function_table->pDestructor;

function_table->pDestructor = NULL;
zend_hash_str_del(function_table, function_name, function_name_length);
function_table->pDestructor = dtor;

/* Keep the remaining copied functions at the start of the table,
* as expected by compiler_globals_dtor(). */
zend_hash_rehash(function_table);
CG(copied_functions_count)--;
return;
}
#endif
zend_hash_str_del(CG(function_table), function_name, function_name_length);
}

Expand Down
45 changes: 45 additions & 0 deletions sapi/fpm/tests/gh21974-disable-functions-worker-shutdown.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
--TEST--
FPM: GH-21974 - disable_functions set in a pool must not break shutdown of the worker
--SKIPIF--
<?php include "skipif.inc"; ?>
--FILE--
<?php

require_once "tester.inc";

$cfg = <<<EOT
[global]
error_log = {{FILE:LOG}}
[unconfined]
listen = {{ADDR}}
pm = static
pm.max_children = 1
; The worker shuts down gracefully after the first request.
pm.max_requests = 1
php_admin_value[disable_functions] = system
EOT;

$code = <<<EOT
<?php
echo function_exists('system') ? 'enabled' : 'disabled';
EOT;

$tester = new FPM\Tester($cfg, $code);
$tester->start();
$tester->expectLogStartNotices();
$tester->request()->expectBody('disabled');
$tester->expectLogNotice('child \d+ exited with code 0 after \d+\.\d+ seconds from start', 'unconfined');
$tester->expectLogNotice('child \d+ started', 'unconfined');
$tester->terminate();
$tester->expectLogTerminatingNotices();
$tester->close();

?>
Done
--EXPECT--
Done
--CLEAN--
<?php
require_once "tester.inc";
FPM\Tester::clean();
?>
Loading