From 8e42ba4357b6a56cb31637edd2f12e5a36cc530a Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Sat, 22 Aug 2020 17:01:00 +0300 Subject: [PATCH] Don't hang when pcntl_fork is disabled (#4039) * Don't hang when pcntl_fork is disabled Fixes vimeo/psalm#3951 * fix CS --- .../Internal/Analyzer/ProjectAnalyzer.php | 18 +++++++++++++++++- src/Psalm/Internal/Fork/Pool.php | 9 +++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index c9b67f74c64..4b795ddd5dc 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -86,6 +86,8 @@ use function array_map; use function end; use Psalm\Internal\Codebase\Taint; +use function ini_get; +use function in_array; /** * @internal @@ -454,13 +456,27 @@ public function server($address = '127.0.0.1:12345', bool $socket_server_mode = exit(1); } fwrite(STDOUT, "Server listening on $address\n"); + + $fork_available = true; if (!extension_loaded('pcntl')) { fwrite(STDERR, "PCNTL is not available. Only a single connection will be accepted\n"); + $fork_available = false; } + + $disabled_functions = array_map('trim', explode(',', ini_get('disable_functions'))); + if (in_array('pcntl_fork', $disabled_functions)) { + fwrite( + STDERR, + "pcntl_fork() is disabled by php configuration (disable_functions directive)." + . " Only a single connection will be accepted\n" + ); + $fork_available = false; + } + while ($socket = stream_socket_accept($tcpServer, -1)) { fwrite(STDOUT, "Connection accepted\n"); stream_set_blocking($socket, false); - if (extension_loaded('pcntl')) { + if ($fork_available) { // If PCNTL is available, fork a child process for the connection // An exit notification will only terminate the child process $pid = pcntl_fork(); diff --git a/src/Psalm/Internal/Fork/Pool.php b/src/Psalm/Internal/Fork/Pool.php index d784a426961..ca16c21d504 100644 --- a/src/Psalm/Internal/Fork/Pool.php +++ b/src/Psalm/Internal/Fork/Pool.php @@ -44,6 +44,8 @@ use function unserialize; use function usleep; use function version_compare; +use function array_map; +use function in_array; /** * Adapted with relatively few changes from @@ -115,6 +117,13 @@ public function __construct( exit(1); } + $disabled_functions = array_map('trim', explode(',', ini_get('disable_functions'))); + if (in_array('pcntl_fork', $disabled_functions)) { + echo "pcntl_fork() is disabled by php configuration (disable_functions directive).\n" + . "Please enable it or run Psalm single-threaded with --threads=1 cli switch.\n"; + exit(1); + } + if (ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && version_compare(PHP_VERSION, '7.3.0') >= 0