From e48d2aef9cd4f692ba08fe16c27e27f56c7ae47c Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Mon, 17 Feb 2020 17:48:01 -0500 Subject: [PATCH] Improve handling when threads cannot be used --- .../Internal/Fork/ForkProcessErrorMessage.php | 13 ++++++ src/Psalm/Internal/Fork/Pool.php | 42 +++++++++++-------- src/psalm.php | 39 ++++++++++------- 3 files changed, 61 insertions(+), 33 deletions(-) create mode 100644 src/Psalm/Internal/Fork/ForkProcessErrorMessage.php diff --git a/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php new file mode 100644 index 00000000000..395bdbbc1ff --- /dev/null +++ b/src/Psalm/Internal/Fork/ForkProcessErrorMessage.php @@ -0,0 +1,13 @@ +message = $message; + } +} diff --git a/src/Psalm/Internal/Fork/Pool.php b/src/Psalm/Internal/Fork/Pool.php index d6aad182bfa..5e013abd7cb 100644 --- a/src/Psalm/Internal/Fork/Pool.php +++ b/src/Psalm/Internal/Fork/Pool.php @@ -177,30 +177,36 @@ public function __construct( $task_done_buffer = ''; - foreach ($task_data_iterator as $i => $task_data) { - $task_result = $task_closure($i, $task_data); - $task_done_message = new ForkTaskDoneMessage($task_result); - $serialized_message = $task_done_buffer . base64_encode(serialize($task_done_message)) . "\n"; + try { + foreach ($task_data_iterator as $i => $task_data) { + $task_result = $task_closure($i, $task_data); - if (strlen($serialized_message) > 200) { - $bytes_written = @fwrite($write_stream, $serialized_message); + $task_done_message = new ForkTaskDoneMessage($task_result); + $serialized_message = $task_done_buffer . base64_encode(serialize($task_done_message)) . "\n"; - if (strlen($serialized_message) !== $bytes_written) { - $task_done_buffer = substr($serialized_message, $bytes_written); + if (strlen($serialized_message) > 200) { + $bytes_written = @fwrite($write_stream, $serialized_message); + + if (strlen($serialized_message) !== $bytes_written) { + $task_done_buffer = substr($serialized_message, $bytes_written); + } else { + $task_done_buffer = ''; + } } else { - $task_done_buffer = ''; + $task_done_buffer = $serialized_message; } - } else { - $task_done_buffer = $serialized_message; } - } - // Execute each child's shutdown closure before - // exiting the process - $results = $shutdown_closure(); + // Execute each child's shutdown closure before + // exiting the process + $results = $shutdown_closure(); + + // Serialize this child's produced results and send them to the parent. + $process_done_message = new ForkProcessDoneMessage($results ?: []); + } catch (\Throwable $t) { + $process_done_message = new ForkProcessErrorMessage($t->getMessage()); + } - // Serialize this child's produced results and send them to the parent. - $process_done_message = new ForkProcessDoneMessage($results ?: []); $serialized_message = $task_done_buffer . base64_encode(serialize($process_done_message)) . "\n"; $bytes_to_write = strlen($serialized_message); @@ -324,6 +330,8 @@ private function readResultsFromChildren() if ($this->task_done_closure !== null) { ($this->task_done_closure)($message->data); } + } elseif ($message instanceof ForkProcessErrorMessage) { + throw new \Exception($message->message); } else { error_log('Child should return ForkMessage - response type=' . gettype($message)); $this->did_have_error = true; diff --git a/src/psalm.php b/src/psalm.php index 991aa04876f..1aee4c13c67 100644 --- a/src/psalm.php +++ b/src/psalm.php @@ -294,11 +294,30 @@ function ($arg) { chdir($current_dir); } -$threads = isset($options['threads']) - ? (int)$options['threads'] - : max(1, ProjectAnalyzer::getCpuCount() - 2); +$in_ci = isset($_SERVER['TRAVIS']) + || isset($_SERVER['CIRCLECI']) + || isset($_SERVER['APPVEYOR']) + || isset($_SERVER['JENKINS_URL']) + || isset($_SERVER['SCRUTINIZER']) + || isset($_SERVER['GITLAB_CI']) + || isset($_SERVER['GITHUB_WORKFLOW']); + +// disable progressbar on CI +if ($in_ci) { + $options['long-progress'] = true; +} + +if (isset($options['threads'])) { + $threads = (int)$options['threads']; +} elseif (isset($options['debug']) || $in_ci) { + $threads = 1; +} else { + $threads = max(1, ProjectAnalyzer::getCpuCount() - 2); +} -if ($threads === 1 +if (!isset($options['threads']) + && !isset($options['debug']) + && $threads === 1 && ini_get('pcre.jit') === '1' && PHP_OS === 'Darwin' && version_compare(PHP_VERSION, '7.3.0') >= 0 @@ -433,18 +452,6 @@ function ($arg) { exit; } -// disable progressbar on CI -if (isset($_SERVER['TRAVIS']) - || isset($_SERVER['CIRCLECI']) - || isset($_SERVER['APPVEYOR']) - || isset($_SERVER['JENKINS_URL']) - || isset($_SERVER['SCRUTINIZER']) - || isset($_SERVER['GITLAB_CI']) - || isset($_SERVER['GITHUB_WORKFLOW']) -) { - $options['long-progress'] = true; -} - $debug = array_key_exists('debug', $options) || array_key_exists('debug-by-line', $options); if ($debug) {