Use global session lock

This commit is contained in:
Daniil Gentili 2020-07-09 21:42:06 +02:00
parent 1e690d1a8f
commit 488a42e6c5
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
5 changed files with 23 additions and 45 deletions

View File

@ -92,7 +92,7 @@ class Logger
/**
* Log rotation loop ID.
*/
private string $rotateId;
private string $rotateId = '';
const ULTRA_VERBOSE = 5;
const VERBOSE = 4;
const NOTICE = 3;
@ -245,7 +245,7 @@ class Logger
/**
* Destructor function.
*/
public function __destruct(): void
public function __destruct()
{
if ($this->rotateId) {
Loop::cancel($this->rotateId);

View File

@ -275,7 +275,7 @@ class WriteLoop extends ResumableSignalLoop
$acks = \array_slice($connection->ack_queue, 0, self::MAX_COUNT);
if ($ackCount = \count($acks)) {
$API->logger->logger("Adding msgs_ack", Logger::ERROR);
$API->logger->logger("Adding msgs_ack", Logger::ULTRA_VERBOSE);
$body = yield from $this->API->getTL()->serializeObject(['type' => ''], ['_' => 'msgs_ack', 'msg_ids' => $acks], 'msgs_ack');
$messages []= [

View File

@ -570,9 +570,6 @@ class MTProto extends AsyncConstruct implements TLCallback
// Report URI
'reportDest',
// Packagist install report state
'packagistReported'
];
}

View File

@ -19,6 +19,8 @@
namespace danog\MadelineProto;
use Amp\Loop;
use function Amp\File\exists;
use function Amp\File\get;
@ -43,7 +45,7 @@ class Serialization
public static function realpaths(string $file): array
{
$file = Tools::absolute($file);
return ['file' => $file, 'lockfile' => $file.'.lock', 'tempfile' => $file.'.temp.session'];
return ['file' => $file, 'lockfile' => $file.'.lock', 'tempfile' => $file.'.temp.session', 'session_lockfile' => $file.'.slock', ];
}
/**
* Unserialize legacy session.
@ -58,6 +60,23 @@ class Serialization
{
$realpaths = self::realpaths($session);
if (yield exists($realpaths['file'])) {
Logger::log('Waiting for exclusive session lock...');
$warningId = Loop::delay(1000, static function () use (&$warningId) {
Logger::log("It seems like the session is busy.");
Logger::log("Telegram does not support starting multiple instances of the same session, make sure no other instance of the session is running.");
$warningId = Loop::repeat(5000, fn () => Logger::log('Still waiting for exclusive session lock...'));
Loop::unreference($warningId);
});
Loop::unreference($warningId);
$unlock = yield Tools::flock($realpaths['session_lockfile'], LOCK_EX, 1);
Loop::cancel($warningId);
Shutdown::addCallback(static function () use ($unlock) {
Logger::log("Unlocking exclusive session lock!");
$unlock();
Logger::log("Unlocked exclusive session lock!");
});
Logger::log("Got exclusive session lock!");
Logger::log('Waiting for shared lock of serialization lockfile...');
$unlock = yield Tools::flock($realpaths['lockfile'], LOCK_SH);
Logger::log('Shared lock acquired, deserializing...');

View File

@ -76,44 +76,6 @@ trait Loop
$this->logger->logger("Self-restarted, restart token ".$_REQUEST['MadelineSelfRestart']);
}
$this->logger->logger($needs_restart ? 'Will self-restart' : 'Will not self-restart');
$backtrace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$lockfile = \dirname(\end($backtrace)['file']).'/bot'.$this->authorization['user']['id'].'.lock';
unset($backtrace);
$try_locking = true;
if (!\file_exists($lockfile)) {
\touch($lockfile);
$lock = \fopen($lockfile, 'r+');
} elseif (isset($GLOBALS['lock'])) {
$try_locking = false;
$lock = $GLOBALS['lock'];
} else {
$lock = \fopen($lockfile, 'r+');
}
if ($try_locking) {
$this->logger->logger('Will try locking');
$try = 1;
$locked = false;
while (!$locked) {
$locked = \flock($lock, LOCK_EX | LOCK_NB);
if (!$locked) {
$this->closeConnection('Bot is already running');
if ($try++ >= 30) {
exit;
}
\sleep(1);
}
}
$this->logger->logger('Locked!');
}
$this->logger->logger("Adding unlock callback!");
$logger =& $this->logger;
$id = Shutdown::addCallback(static function () use ($lock, $logger) {
$logger->logger("Unlocking lock!");
\flock($lock, LOCK_UN);
\fclose($lock);
$logger->logger("Unlocked lock!");
});
$this->logger->logger("Added unlock callback with id $id!");
if ($needs_restart) {
$this->logger->logger("Adding restart callback!");
$id = Shutdown::addCallback(static function () use (&$logger) {