From 44b5b659f273cac7e2808a88b932715d4174d3db Mon Sep 17 00:00:00 2001 From: Kristofer Berggren Date: Sat, 6 Jul 2024 16:45:40 +0800 Subject: [PATCH] fix full sync hang for large mailboxes --- src/imapmanager.cpp | 53 ++++++++++++++++++++++++++------------------- src/imapmanager.h | 2 ++ src/nmail.1 | 2 +- src/version.cpp | 2 +- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/imapmanager.cpp b/src/imapmanager.cpp index 71599cf..2164285 100644 --- a/src/imapmanager.cpp +++ b/src/imapmanager.cpp @@ -70,7 +70,7 @@ ImapManager::~ImapManager() } m_Running = false; - LOG_IF_NOT_EQUAL(write(m_Pipe[1], "1", 1), 1); + PipeWriteOne(m_Pipe); if (m_ExitedCond.wait_for(lock, std::chrono::seconds(3)) != std::cv_status::timeout) { @@ -103,7 +103,7 @@ ImapManager::~ImapManager() std::unique_lock lock(m_ExitedCacheCondMutex); m_CacheRunning = false; - LOG_IF_NOT_EQUAL(write(m_CachePipe[1], "1", 1), 1); + PipeWriteOne(m_CachePipe); if (m_ExitedCacheCond.wait_for(lock, std::chrono::seconds(2)) != std::cv_status::timeout) { @@ -151,14 +151,14 @@ void ImapManager::AsyncRequest(const ImapManager::Request& p_Request) { std::lock_guard lock(m_CacheQueueMutex); m_CacheRequests.push_front(p_Request); - LOG_IF_NOT_EQUAL(write(m_CachePipe[1], "1", 1), 1); + PipeWriteOne(m_CachePipe); } if (m_Connecting || m_OnceConnected) { std::lock_guard lock(m_QueueMutex); m_Requests.push_front(p_Request); - LOG_IF_NOT_EQUAL(write(m_Pipe[1], "1", 1), 1); + PipeWriteOne(m_Pipe); ProgressCountRequestAdd(p_Request, false /* p_IsPrefetch */); } else @@ -173,7 +173,7 @@ void ImapManager::PrefetchRequest(const ImapManager::Request& p_Request) { std::lock_guard lock(m_QueueMutex); m_PrefetchRequests[p_Request.m_PrefetchLevel].push_front(p_Request); - LOG_IF_NOT_EQUAL(write(m_Pipe[1], "1", 1), 1); + PipeWriteOne(m_Pipe); ProgressCountRequestAdd(p_Request, true /* p_IsPrefetch */); } else @@ -188,7 +188,7 @@ void ImapManager::AsyncAction(const ImapManager::Action& p_Action) { std::lock_guard lock(m_QueueMutex); m_Actions.push_front(p_Action); - LOG_IF_NOT_EQUAL(write(m_Pipe[1], "1", 1), 1); + PipeWriteOne(m_Pipe); } else { @@ -519,15 +519,8 @@ void ImapManager::Process() else if (m_Running && !authRefreshNeeded && ((selrv > 0) || !isQueueEmpty)) { - int len = 0; - ioctl(m_Pipe[0], FIONREAD, &len); - if (len > 0) - { - std::vector buf(len); - LOG_IF_NOT_EQUAL(read(m_Pipe[0], &buf[0], len), len); - } - m_QueueMutex.lock(); + PipeReadAll(m_Pipe); while (m_Running && !authRefreshNeeded && m_OnceConnected && @@ -817,15 +810,8 @@ void ImapManager::CacheProcess() if ((selrv != 0) && FD_ISSET(m_CachePipe[0], &fds)) { - int len = 0; - ioctl(m_CachePipe[0], FIONREAD, &len); - if (len > 0) - { - std::vector buf(len); - LOG_IF_NOT_EQUAL(read(m_CachePipe[0], &buf[0], len), len); - } - m_CacheQueueMutex.lock(); + PipeReadAll(m_CachePipe); while (m_CacheRunning && !m_CacheRequests.empty()) { @@ -1106,3 +1092,26 @@ float ImapManager::GetProgressPercentage(const Request& p_Request, bool p_IsPref return progress; } + +void ImapManager::PipeWriteOne(int p_Fds[2]) +{ + const int readFd = p_Fds[0]; + int len = 0; + ioctl(readFd, FIONREAD, &len); + if (len > 0) return; // bail out if already signaled + + const int writeFd = p_Fds[1]; + LOG_IF_NOT_EQUAL(write(writeFd, "1", 1), 1); +} + +void ImapManager::PipeReadAll(int p_Fds[2]) +{ + const int readFd = p_Fds[0]; + int len = 0; + ioctl(readFd, FIONREAD, &len); + if (len > 0) + { + std::vector buf(len); + LOG_IF_NOT_EQUAL(read(readFd, &buf[0], len), len); + } +} diff --git a/src/imapmanager.h b/src/imapmanager.h index 8abfaba..419aaa2 100644 --- a/src/imapmanager.h +++ b/src/imapmanager.h @@ -168,6 +168,8 @@ class ImapManager void ProgressCountRequestDone(const Request& p_Request, bool p_IsPrefetch); void ProgressCountReset(bool p_IsPrefetch); float GetProgressPercentage(const Request& p_Request, bool p_IsPrefetch); + void PipeWriteOne(int p_Fds[2]); + void PipeReadAll(int p_Fds[2]); private: Imap m_Imap; diff --git a/src/nmail.1 b/src/nmail.1 index b8c575e..ca085bf 100644 --- a/src/nmail.1 +++ b/src/nmail.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man. -.TH NMAIL "1" "June 2024" "nmail 5.1.2" "User Commands" +.TH NMAIL "1" "July 2024" "nmail 5.1.3" "User Commands" .SH NAME nmail \- ncurses mail .SH SYNOPSIS diff --git a/src/version.cpp b/src/version.cpp index 8f3d83b..629ccd3 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -7,7 +7,7 @@ #include "version.h" -#define NMAIL_VERSION "5.1.2" +#define NMAIL_VERSION "5.1.3" std::string Version::GetBuildOs() {