diff --git a/src/Console/Command/Compile.php b/src/Console/Command/Compile.php index cbb7207e6..5272aab63 100644 --- a/src/Console/Command/Compile.php +++ b/src/Console/Command/Compile.php @@ -37,6 +37,7 @@ use KevinGH\Box\Configuration\Configuration; use KevinGH\Box\Console\Logger\CompilerLogger; use KevinGH\Box\Console\MessageRenderer; +use KevinGH\Box\Console\OpenFileDescriptorLimiter; use KevinGH\Box\Constants; use KevinGH\Box\MapFile; use KevinGH\Box\Phar\CompressionAlgorithm; @@ -62,7 +63,6 @@ use function implode; use function is_callable; use function is_string; -use function KevinGH\Box\bump_open_file_descriptor_limit; use function KevinGH\Box\check_php_settings; use function KevinGH\Box\disable_parallel_processing; use function KevinGH\Box\format_size; @@ -221,7 +221,7 @@ public function execute(IO $io): int // Adding files might result in opening a lot of files. Either because not parallelized or when creating the // workers for parallelization. // As a result, we bump the file descriptor to an arbitrary number to ensure this process can run correctly - $restoreLimit = bump_open_file_descriptor_limit(2048, $io); + $restoreLimit = OpenFileDescriptorLimiter::bumpLimit(2048, $io); try { $box = $this->createPhar($config, $logger, $io, $debug); @@ -721,7 +721,7 @@ private static function configureCompressionAlgorithm( ), ); - $restoreLimit = bump_open_file_descriptor_limit(count($box), $io); + $restoreLimit = OpenFileDescriptorLimiter::bumpLimit(count($box), $io); try { $extension = $box->compress($algorithm); diff --git a/src/Console/OpenFileDescriptorLimiter.php b/src/Console/OpenFileDescriptorLimiter.php new file mode 100644 index 000000000..e2d887ed4 --- /dev/null +++ b/src/Console/OpenFileDescriptorLimiter.php @@ -0,0 +1,98 @@ + + * Théo Fidry + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace KevinGH\Box\Console; + +use Closure; +use Fidry\Console\IO; +use KevinGH\Box\NotInstantiable; +use Symfony\Component\Console\Output\OutputInterface; +use function function_exists; +use function posix_getrlimit; +use function posix_setrlimit; +use function sprintf; +use const POSIX_RLIMIT_INFINITY; +use const POSIX_RLIMIT_NOFILE; + +/** + * @internal + */ +final class OpenFileDescriptorLimiter +{ + use NotInstantiable; + + private const LIMIT_MARGIN = 128; + + /** + * Bumps the maximum number of open file descriptor if necessary. + * + * @return Closure Callable to call to restore the original maximum number of open files descriptors + */ + public static function bumpLimit(int $count, IO $io): Closure + { + $count += self::LIMIT_MARGIN; // Add a little extra for good measure + + if (false === function_exists('posix_getrlimit') || false === function_exists('posix_setrlimit')) { + $io->writeln( + '[debug] Could not check the maximum number of open file descriptors: the functions "posix_getrlimit()" and ' + .'"posix_setrlimit" could not be found.', + OutputInterface::VERBOSITY_DEBUG, + ); + + // TODO: loverage noop + return static function (): void {}; + } + + $softLimit = posix_getrlimit()['soft openfiles']; + $hardLimit = posix_getrlimit()['hard openfiles']; + + if ($softLimit >= $count) { + return static function (): void {}; + } + + $io->writeln( + sprintf( + '[debug] Increased the maximum number of open file descriptors from ("%s", "%s") to ("%s", "%s")' + .'', + $softLimit, + $hardLimit, + $count, + 'unlimited', + ), + OutputInterface::VERBOSITY_DEBUG, + ); + + posix_setrlimit( + POSIX_RLIMIT_NOFILE, + $count, + 'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit, + ); + + return static function () use ($io, $softLimit, $hardLimit): void { + // TODO: this check looks redundant + if (function_exists('posix_setrlimit') && isset($softLimit, $hardLimit)) { + posix_setrlimit( + POSIX_RLIMIT_NOFILE, + $softLimit, + 'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit, + ); + + $io->writeln( + '[debug] Restored the maximum number of open file descriptors', + OutputInterface::VERBOSITY_DEBUG, + ); + } + }; + } +} diff --git a/src/functions.php b/src/functions.php index 6b8f05019..58d4ef84f 100644 --- a/src/functions.php +++ b/src/functions.php @@ -22,7 +22,6 @@ use Phar; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Logger\ConsoleLogger; -use Symfony\Component\Console\Output\OutputInterface; use Webmozart\Assert\Assert; use function bin2hex; use function class_alias; @@ -31,18 +30,13 @@ use function define; use function defined; use function floor; -use function function_exists; use function is_float; use function is_int; use function log; use function number_format; -use function posix_getrlimit; -use function posix_setrlimit; use function random_bytes; use function sprintf; use function str_replace; -use const POSIX_RLIMIT_INFINITY; -use const POSIX_RLIMIT_NOFILE; /** * @private @@ -241,63 +235,3 @@ static function (int $code, string $message, string $file = '', int $line = -1): }, ); } - -/** - * Bumps the maximum number of open file descriptor if necessary. - * - * @return Closure callable to call to restore the original maximum number of open files descriptors - */ -function bump_open_file_descriptor_limit(int $count, IO $io): Closure -{ - $count += 128; // Add a little extra for good measure - - if (false === function_exists('posix_getrlimit') || false === function_exists('posix_setrlimit')) { - $io->writeln( - '[debug] Could not check the maximum number of open file descriptors: the functions "posix_getrlimit()" and ' - .'"posix_setrlimit" could not be found.', - OutputInterface::VERBOSITY_DEBUG, - ); - - return static function (): void {}; - } - - $softLimit = posix_getrlimit()['soft openfiles']; - $hardLimit = posix_getrlimit()['hard openfiles']; - - if ($softLimit >= $count) { - return static function (): void {}; - } - - $io->writeln( - sprintf( - '[debug] Increased the maximum number of open file descriptors from ("%s", "%s") to ("%s", "%s")' - .'', - $softLimit, - $hardLimit, - $count, - 'unlimited', - ), - OutputInterface::VERBOSITY_DEBUG, - ); - - posix_setrlimit( - POSIX_RLIMIT_NOFILE, - $count, - 'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit, - ); - - return static function () use ($io, $softLimit, $hardLimit): void { - if (function_exists('posix_setrlimit') && isset($softLimit, $hardLimit)) { - posix_setrlimit( - POSIX_RLIMIT_NOFILE, - $softLimit, - 'unlimited' === $hardLimit ? POSIX_RLIMIT_INFINITY : $hardLimit, - ); - - $io->writeln( - '[debug] Restored the maximum number of open file descriptors', - OutputInterface::VERBOSITY_DEBUG, - ); - } - }; -}