From 26aa11ab2ca86b10429d0c3831e325ba65aaf176 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 27 Jan 2023 19:30:08 +0100 Subject: [PATCH] Test fibers before first login --- src/API.php | 12 +++++++++++ src/InternalDoc.php | 26 +++++++++++++++++++++++ src/MTProtoTools/Files.php | 2 +- src/Tools.php | 42 +++++++++++++++++++++++++++++++++----- tests/makephar.sh | 2 ++ 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/API.php b/src/API.php index bacddc317..88724bfba 100644 --- a/src/API.php +++ b/src/API.php @@ -154,6 +154,18 @@ final class API extends AbstractAPI return; // OK } + $result = Tools::testFibers(100); + + if ($result['maxFibers'] < 100) { + $message = "The maximum number of startable fibers is smaller than 100 ({$result['maxFibers']}): follow the instructions in https://t.me/MadelineProto/596 to fix."; + if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') { + echo $message.'
'; + } + $file = 'MadelineProto'; + $line = 1; + return new Exception($message, 0, null, $file, $line); + } + if (!$settings instanceof Settings) { $newSettings = new Settings; $newSettings->merge($settings); diff --git a/src/InternalDoc.php b/src/InternalDoc.php index 363056844..e6a855365 100644 --- a/src/InternalDoc.php +++ b/src/InternalDoc.php @@ -792,6 +792,23 @@ abstract class InternalDoc { return $this->wrapper->getAPI()->{__FUNCTION__}(); } + /** + * Get current number of memory-mapped regions, UNIX only. + * @return ?int + */ + public static function getMaps(): ?int + { + return \danog\MadelineProto\Tools::getMaps(); + } + /** + * Get maximum number of memory-mapped regions, UNIX only. + * Use testFibers to get the maximum number of fibers on any platform. + * @return ?int + */ + public static function getMaxMaps(): ?int + { + return \danog\MadelineProto\Tools::getMaxMaps(); + } /** * Get TL namespaces. */ @@ -1458,6 +1475,15 @@ abstract class InternalDoc { return $this->wrapper->getAPI()->{__FUNCTION__}($params, $key); } + /** + * Test fibers. + * + * @return array{maxFibers: int, realMemoryMb: int, maps: ?int, maxMaps: ?int} + */ + public static function testFibers(int $fiberCount = 100000): array + { + return \danog\MadelineProto\Tools::testFibers($fiberCount); + } /** * Create an artificial timeout for any Generator or Promise. * diff --git a/src/MTProtoTools/Files.php b/src/MTProtoTools/Files.php index 37c7ef630..43f02023a 100644 --- a/src/MTProtoTools/Files.php +++ b/src/MTProtoTools/Files.php @@ -987,7 +987,7 @@ trait Files ); break; } catch (RPCErrorException $e) { - if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0) { + if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0 || $e->rpc === '-503') { Tools::sleep(1); continue; } diff --git a/src/Tools.php b/src/Tools.php index fcf6c866a..6932de274 100644 --- a/src/Tools.php +++ b/src/Tools.php @@ -43,14 +43,16 @@ use function unpack; abstract class Tools extends AsyncTools { /** - * @internal Test fibers + * Test fibers. + * + * @return array{maxFibers: int, realMemoryMb: int, maps: ?int, maxMaps: ?int} */ - public static function testFibers(): ?array + public static function testFibers(int $fiberCount = 100000): array { \ini_set('memory_limit', -1); $f = []; - for ($x = 0; $x < 100000; $x++) { + for ($x = 0; $x < $fiberCount; $x++) { try { $f []= $cur = new Fiber(function (): void { Fiber::suspend(); @@ -63,10 +65,40 @@ abstract class Tools extends AsyncTools return [ 'maxFibers' => $x, 'realMemoryMb' => (int) (\memory_get_usage(true)/1024/1024), - 'maps' => \substr_count(@\file_get_contents('/proc/self/maps'), "\n")-1, - 'maxMaps' => (int) @\file_get_contents('/proc/sys/vm/max_map_count'), + 'maps' => self::getMaps(), + 'maxMaps' => self::getMaxMaps(), ]; } + /** + * Get current number of memory-mapped regions, UNIX only. + */ + public static function getMaps(): ?int + { + try { + if (\file_exists('/proc/self/maps')) { + return \substr_count(@\file_get_contents('/proc/self/maps'), "\n")-1; + } + $pid = \getmypid(); + if (\file_exists("/proc/$pid/maps")) { + return \substr_count(@\file_get_contents("/proc/$pid/maps"), "\n")-1; + } + return null; + } catch (\Throwable) { + return null; + } + } + /** + * Get maximum number of memory-mapped regions, UNIX only. + * Use testFibers to get the maximum number of fibers on any platform. + */ + public static function getMaxMaps(): ?int + { + try { + return ((int) @\file_get_contents('/proc/sys/vm/max_map_count')) ?: null; + } catch (\Throwable) { + return null; + } + } /** * Sanify TL obtained from JSON for TL serialization. * diff --git a/tests/makephar.sh b/tests/makephar.sh index 20aa16efd..c173df2e7 100755 --- a/tests/makephar.sh +++ b/tests/makephar.sh @@ -86,6 +86,8 @@ echo '{ php $(which composer) update --no-cache php $(which composer) dumpautoload --optimize rm -rf vendor/danog/madelineproto/docs vendor/danog/madelineproto/vendor-bin +mkdir -p vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner +cp vendor/danog/madelineproto/src/Ipc/Runner/entry.php vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner cd .. branch="-$BRANCH"