Skip to content

Commit

Permalink
fix full sync hang for large mailboxes
Browse files Browse the repository at this point in the history
  • Loading branch information
d99kris committed Jul 6, 2024
1 parent 1341793 commit 44b5b65
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 24 deletions.
53 changes: 31 additions & 22 deletions src/imapmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -103,7 +103,7 @@ ImapManager::~ImapManager()
std::unique_lock<std::mutex> 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)
{
Expand Down Expand Up @@ -151,14 +151,14 @@ void ImapManager::AsyncRequest(const ImapManager::Request& p_Request)
{
std::lock_guard<std::mutex> 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<std::mutex> 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
Expand All @@ -173,7 +173,7 @@ void ImapManager::PrefetchRequest(const ImapManager::Request& p_Request)
{
std::lock_guard<std::mutex> 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
Expand All @@ -188,7 +188,7 @@ void ImapManager::AsyncAction(const ImapManager::Action& p_Action)
{
std::lock_guard<std::mutex> lock(m_QueueMutex);
m_Actions.push_front(p_Action);
LOG_IF_NOT_EQUAL(write(m_Pipe[1], "1", 1), 1);
PipeWriteOne(m_Pipe);
}
else
{
Expand Down Expand Up @@ -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<char> 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 &&
Expand Down Expand Up @@ -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<char> 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())
{
Expand Down Expand Up @@ -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<char> buf(len);
LOG_IF_NOT_EQUAL(read(readFd, &buf[0], len), len);
}
}
2 changes: 2 additions & 0 deletions src/imapmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/nmail.1
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "version.h"

#define NMAIL_VERSION "5.1.2"
#define NMAIL_VERSION "5.1.3"

std::string Version::GetBuildOs()
{
Expand Down

0 comments on commit 44b5b65

Please sign in to comment.