From 0980bd8718936d7e9e4503c57bfbd7e8e04e2be4 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 8 Apr 2021 15:38:55 +0200 Subject: [PATCH] Misc fixes --- src/danog/MadelineProto/API.php | 6 ++- .../MTProtoSession/ResponseHandler.php | 2 + src/danog/MadelineProto/SessionPaths.php | 42 +++++++++++++------ .../MadelineProto/Settings/Connection.php | 2 +- src/danog/MadelineProto/Tools.php | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php index 9f4c11709..868fa48f9 100644 --- a/src/danog/MadelineProto/API.php +++ b/src/danog/MadelineProto/API.php @@ -269,7 +269,7 @@ class API extends InternalDoc if ($unserialized === 0) { // Timeout - throw new \RuntimeException("Could not connect to MadelineProto, please check the logs for more details."); + throw new Exception("Could not connect to MadelineProto, please check the logs for more details."); } elseif ($unserialized instanceof \Throwable) { // IPC server error, try fetching full session return yield from $this->connectToMadelineProto($settings, true); @@ -370,6 +370,7 @@ class API extends InternalDoc */ public function startAndLoop(string $eventHandler): void { + $this->forceFull = true; while (true) { try { Tools::wait($this->startAndLoopAsync($eventHandler)); @@ -399,6 +400,7 @@ class API extends InternalDoc try { $promises = []; foreach ($instances as $k => $instance) { + $instance->forceFull = true; $instance->start(['async' => false]); $promises []= $instance->startAndLoopAsync($eventHandler[$k]); } @@ -422,8 +424,8 @@ class API extends InternalDoc public function startAndLoopAsync(string $eventHandler): \Generator { $errors = []; - $this->async(true); $this->forceFull = true; + $this->async(true); if (!yield from $this->reconnectFull()) { return; diff --git a/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php b/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php index 25c5a9eb4..1137f46d5 100644 --- a/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php @@ -205,6 +205,8 @@ trait ResponseHandler $this->methodRecall('', ['message_id' => $requestId, 'postpone' => true]); return; case 20: + $request->setMsgId(null); + $request->setSeqNo(null); $this->methodRecall('', ['message_id' => $requestId, 'postpone' => true]); return; case 16: diff --git a/src/danog/MadelineProto/SessionPaths.php b/src/danog/MadelineProto/SessionPaths.php index f0ca636d1..198f6a7d0 100644 --- a/src/danog/MadelineProto/SessionPaths.php +++ b/src/danog/MadelineProto/SessionPaths.php @@ -27,6 +27,7 @@ use danog\MadelineProto\Ipc\IpcState; use function Amp\File\exists; use function Amp\File\open; use function Amp\File\rename; +use function Amp\File\stat; /** * Session path information. @@ -91,13 +92,22 @@ class SessionPaths */ public function serialize(object $object, string $path): \Generator { - $file = yield open("$path.temp.php", 'bw+'); - yield $file->write(Serialization::PHP_HEADER); - yield $file->write(\chr(Serialization::VERSION)); - yield $file->write(\serialize($object)); - yield $file->close(); + Logger::log("Waiting for exclusive lock of $path.lock..."); + $unlock = yield from Tools::flockGenerator("$path.lock", LOCK_EX, 0.1); - yield rename("$path.temp.php", $path); + try { + Logger::log("Got exclusive lock of $path.temp.php.lock..."); + + $file = yield open("$path.temp.php", 'bw+'); + yield $file->write(Serialization::PHP_HEADER); + yield $file->write(\chr(Serialization::VERSION)); + yield $file->write(\serialize($object)); + yield $file->close(); + + yield \rename("$path.temp.php", $path); + } finally { + $unlock(); + } } /** @@ -119,14 +129,22 @@ class SessionPaths } $headerLen = \strlen(Serialization::PHP_HEADER) + 1; - $file = yield open($path, 'rb'); - $size = yield \stat($path); - $size = $size['size'] ?? $headerLen; + Logger::log("Waiting for shared lock of $path.lock..."); + $unlock = yield from Tools::flockGenerator("$path.lock", LOCK_SH, 0.1); - yield $file->seek($headerLen); // Skip version for now - $unserialized = \unserialize((yield $file->read($size - $headerLen)) ?? ''); - yield $file->close(); + try { + Logger::log("Got shared lock of $path.lock..."); + $file = yield open($path, 'rb'); + $size = yield stat($path); + $size = $size['size'] ?? $headerLen; + + yield $file->seek($headerLen); // Skip version for now + $unserialized = \unserialize((yield $file->read($size - $headerLen)) ?? ''); + yield $file->close(); + } finally { + $unlock(); + } return $unserialized; } diff --git a/src/danog/MadelineProto/Settings/Connection.php b/src/danog/MadelineProto/Settings/Connection.php index 49ef24305..56e2d7f78 100644 --- a/src/danog/MadelineProto/Settings/Connection.php +++ b/src/danog/MadelineProto/Settings/Connection.php @@ -77,7 +77,7 @@ class Connection extends SettingsAbstract /** * Whether to use ipv6. */ - protected bool $ipv6; + protected bool $ipv6 = false; /** * Connection timeout. diff --git a/src/danog/MadelineProto/Tools.php b/src/danog/MadelineProto/Tools.php index a1f52c691..cfd2d23d6 100644 --- a/src/danog/MadelineProto/Tools.php +++ b/src/danog/MadelineProto/Tools.php @@ -603,7 +603,7 @@ abstract class Tools extends StrTools * @param ?Promise $token Cancellation token * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails. * - * @return Promise + * @return Promise<$token is null ? callable : ?callable> */ public static function flock(string $file, int $operation, float $polling = 0.1, ?Promise $token = null, $failureCb = null): Promise {