4343use function array_chunk ;
4444use function array_filter ;
4545use function array_map ;
46+ use function register_shutdown_function ;
4647use function sprintf ;
4748
4849class 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