Skip to content

Commit 4773c1d

Browse files
ChristophWurstkesselb
authored andcommitted
fix: unlock mailboxes after OOM
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
1 parent 77e6973 commit 4773c1d

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

lib/Service/Sync/ImapToDbSynchronizer.php

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
use function array_chunk;
4444
use function array_filter;
4545
use function array_map;
46+
use function register_shutdown_function;
4647
use function sprintf;
4748

4849
class ImapToDbSynchronizer {
@@ -214,6 +215,14 @@ public function sync(Account $account,
214215
?array $knownUids = null,
215216
bool $force = false,
216217
bool $batchSync = false): bool {
218+
/*
219+
* Reserve for unlocking
220+
*
221+
* Important: reserve early to avoid OOM after locking but before the
222+
* shutdown handler registration
223+
*/
224+
$oomBuffer = str_repeat(' ', 1024 * 1024);
225+
217226
$rebuildThreads = true;
218227
if ($mailbox->getSelectable() === false) {
219228
return $rebuildThreads;
@@ -249,6 +258,11 @@ public function sync(Account $account,
249258
$this->mailboxMapper->lockForVanishedSync($mailbox);
250259
}
251260

261+
register_shutdown_function(function () use ($force, $criteria, $logger, $mailbox, &$oomBuffer) {
262+
unset($oomBuffer);
263+
$this->unlockMailbox($force, $criteria, $logger, $mailbox);
264+
});
265+
252266
try {
253267
if ($force
254268
|| $mailbox->getSyncNewToken() === null
@@ -281,18 +295,7 @@ public function sync(Account $account,
281295
} catch (Throwable $e) {
282296
throw new ServiceException('Sync failed for ' . $account->getId() . ':' . $mailbox->getName() . ': ' . $e->getMessage(), 0, $e);
283297
} finally {
284-
if ($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS)) {
285-
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from vanished messages sync');
286-
$this->mailboxMapper->unlockFromVanishedSync($mailbox);
287-
}
288-
if ($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS)) {
289-
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from changed messages sync');
290-
$this->mailboxMapper->unlockFromChangedSync($mailbox);
291-
}
292-
if ($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS)) {
293-
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from new messages sync');
294-
$this->mailboxMapper->unlockFromNewSync($mailbox);
295-
}
298+
$this->unlockMailbox($force, $criteria, $logger, $mailbox);
296299
}
297300

298301
if (!$batchSync) {
@@ -308,6 +311,24 @@ public function sync(Account $account,
308311
return $rebuildThreads;
309312
}
310313

314+
private function unlockMailbox(bool $force, int $criteria, LoggerInterface $logger, Mailbox $mailbox): void {
315+
if (($force || ($criteria & Horde_Imap_Client::SYNC_VANISHEDUIDS))
316+
&& $mailbox->getSyncVanishedLock() !== null) {
317+
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from vanished messages sync');
318+
$this->mailboxMapper->unlockFromVanishedSync($mailbox);
319+
}
320+
if (($force || ($criteria & Horde_Imap_Client::SYNC_FLAGSUIDS))
321+
&& $mailbox->getSyncChangedLock() !== null) {
322+
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from changed messages sync');
323+
$this->mailboxMapper->unlockFromChangedSync($mailbox);
324+
}
325+
if (($force || ($criteria & Horde_Imap_Client::SYNC_NEWMSGSUIDS))
326+
&& $mailbox->getSyncNewLock() !== null) {
327+
$logger->debug('Unlocking mailbox ' . $mailbox->getId() . ' from new messages sync');
328+
$this->mailboxMapper->unlockFromNewSync($mailbox);
329+
}
330+
}
331+
311332
/**
312333
* @throws ServiceException
313334
* @throws IncompleteSyncException

0 commit comments

Comments
 (0)