Skip to content
Draft
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
56 changes: 50 additions & 6 deletions src/Runtime.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use const PHP_BINARY;
use const PHP_SAPI;
use const PHP_VERSION;
use function array_key_exists;
use function array_map;
use function array_merge;
use function assert;
Expand All @@ -32,6 +33,7 @@
use function phpversion;
use function proc_close;
use function proc_open;
use function reset;
use function sprintf;
use function stream_get_contents;
use function strrpos;
Expand Down Expand Up @@ -246,7 +248,8 @@ public function hasPCOV(): bool
* Parses the loaded php.ini file (if any) as well as all
* additional php.ini files from the additional ini dir into a
* single merged map of settings, and also obtains the compiled-in
* defaults by spawning a `php -n` child once per process.
* defaults (read in-process from ini_get_all() where available,
* otherwise by spawning a `php -n` child once per process).
* Then checks for each setting passed via the `$values` parameter
* whether the runtime value (`ini_get()`) differs from what the
* ini files specified or, when a setting is not configured in any
Expand Down Expand Up @@ -388,11 +391,16 @@ private function parseLoadedIniFiles(): array
}

/**
* Returns the compiled-in default values of every ini setting by
* spawning a `php -n` child process once and caching the result
* for the lifetime of the PHP process. When the child cannot be
* launched or its output is unusable, an empty array is returned
* and cached so the failure is not retried.
* Returns the compiled-in default values of every ini setting,
* caching the result for the lifetime of the PHP process.
*
* On PHP versions where ini_get_all() exposes the
* `builtin_default_value` of each setting (see
* https://github.com/php/php-src/issues/22133) the defaults are
* read in-process. On older versions they are
* obtained by spawning a `php -n` child process once, which is
* avoided where possible because forking can trigger unwanted
* side effects from extension fork handlers.
*
* @return array<string, string>
*/
Expand All @@ -402,6 +410,42 @@ private static function compiledDefaults(): array
return self::$compiledDefaults;
}

$allSettings = ini_get_all(null, true);

if ($allSettings !== false) {
$first = reset($allSettings);

if (is_array($first) && array_key_exists('builtin_default_value', $first)) {
self::$compiledDefaults = [];

foreach ($allSettings as $key => $info) {
if (!is_string($key) || !is_array($info)) {
continue;
}

if (isset($info['builtin_default_value']) && is_string($info['builtin_default_value'])) {
self::$compiledDefaults[$key] = $info['builtin_default_value'];
}
}

return self::$compiledDefaults;
}
}

return self::compiledDefaultsViaChildProcess();
}

/**
* Returns the compiled-in default values of every ini setting by
* spawning a `php -n` child process once and caching the result
* for the lifetime of the PHP process. When the child cannot be
* launched or its output is unusable, an empty array is returned
* and cached so the failure is not retried.
*
* @return array<string, string>
*/
private static function compiledDefaultsViaChildProcess(): array
{
self::$compiledDefaults = [];

$process = proc_open(
Expand Down
Loading