Commit 550771fd authored by Kevin J. McCarthy's avatar Kevin J. McCarthy

Work around open mailbox monitor code check issue.

The monitor code is too fast, and can result in all the changes for a
single directory stat update being missed.

Work around this issue by not recording stat time updates when the
check_mailbox() is triggered by the monitor.  This will cause the next
subsequent check to take another look.
parent fc040a5b
Pipeline #24557653 passed with stages
in 13 minutes and 27 seconds
......@@ -37,6 +37,9 @@
#endif
#include "mutt_curses.h"
#include "buffy.h"
#ifdef USE_INOTIFY
#include "monitor.h"
#endif
#include <sys/stat.h>
#include <sys/types.h>
......@@ -2123,9 +2126,21 @@ static int maildir_check_mailbox (CONTEXT * ctx, int *index_hint)
if (!changed)
return 0; /* nothing to do */
/* update the modification times on the mailbox */
mutt_get_stat_timespec (&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
mutt_get_stat_timespec (&ctx->mtime, &st_new, MUTT_STAT_MTIME);
/* Update the modification times on the mailbox.
*
* The monitor code notices changes in the open mailbox too quickly.
* In practice, this sometimes leads to all the new messages not being
* noticed during the SAME group of mtime stat updates. To work around
* the problem, don't update the stat times for a monitor caused check. */
#ifdef USE_INOTIFY
if (MonitorContextChanged)
MonitorContextChanged = 0;
else
#endif
{
mutt_get_stat_timespec (&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
mutt_get_stat_timespec (&ctx->mtime, &st_new, MUTT_STAT_MTIME);
}
/* do a fast scan of just the filenames in
* the subdirectories that have changed.
......@@ -2287,8 +2302,21 @@ static int mh_check_mailbox (CONTEXT * ctx, int *index_hint)
if (!modified)
return 0;
mutt_get_stat_timespec (&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
mutt_get_stat_timespec (&ctx->mtime, &st, MUTT_STAT_MTIME);
/* Update the modification times on the mailbox.
*
* The monitor code notices changes in the open mailbox too quickly.
* In practice, this sometimes leads to all the new messages not being
* noticed during the SAME group of mtime stat updates. To work around
* the problem, don't update the stat times for a monitor caused check. */
#ifdef USE_INOTIFY
if (MonitorContextChanged)
MonitorContextChanged = 0;
else
#endif
{
mutt_get_stat_timespec (&data->mtime_cur, &st_cur, MUTT_STAT_MTIME);
mutt_get_stat_timespec (&ctx->mtime, &st, MUTT_STAT_MTIME);
}
memset (&mhs, 0, sizeof (mhs));
......
......@@ -52,6 +52,8 @@ static size_t PollFdsCount = 0;
static size_t PollFdsLen = 0;
static struct pollfd *PollFds;
static int MonitorContextDescriptor = -1;
typedef struct monitorinfo_t
{
short magic;
......@@ -193,6 +195,9 @@ static int monitor_handle_ignore (int descr)
dprint (3, (debugfile, "monitor: cleanup watch (implicitly removed) - descriptor=%d\n", descr));
}
if (MonitorContextDescriptor == descr)
MonitorContextDescriptor = new_descr;
if (new_descr == -1)
{
monitor_delete (iter);
......@@ -275,6 +280,8 @@ int mutt_monitor_poll (void)
event->wd, event->mask));
if (event->mask & IN_IGNORED)
monitor_handle_ignore (event->wd);
else if (event->wd == MonitorContextDescriptor)
MonitorContextChanged = 1;
ptr += sizeof(struct inotify_event) + event->len;
}
}
......@@ -374,7 +381,11 @@ int mutt_monitor_add (BUFFY *buffy)
descr = monitor_resolve (&info, buffy);
if (descr != RESOLVERES_OK_NOTEXISTING)
{
if (!buffy && (descr == RESOLVERES_OK_EXISTING))
MonitorContextDescriptor = info.monitor->descr;
return descr == RESOLVERES_OK_EXISTING ? 0 : -1;
}
mask = info.isdir ? INOTIFY_MASK_DIR : INOTIFY_MASK_FILE;
if ((INotifyFd == -1 && monitor_init () == -1)
......@@ -385,6 +396,9 @@ int mutt_monitor_add (BUFFY *buffy)
}
dprint (3, (debugfile, "monitor: inotify_add_watch descriptor=%d for '%s'\n", descr, info.path));
if (!buffy)
MonitorContextDescriptor = descr;
monitor_create (&info, descr);
return 0;
}
......@@ -421,6 +435,9 @@ int mutt_monitor_remove (BUFFY *buffy)
inotify_rm_watch(info.monitor->descr, INotifyFd);
dprint (3, (debugfile, "monitor: inotify_rm_watch for '%s' descriptor=%d\n", info.path, info.monitor->descr));
if (!buffy && (MonitorContextDescriptor == info.monitor->descr))
MonitorContextDescriptor = -1;
monitor_delete (info.monitor);
monitor_check_free ();
return 0;
......
......@@ -20,6 +20,7 @@
#define MONITOR_H
WHERE int MonitorFilesChanged INITVAL (0);
WHERE int MonitorContextChanged INITVAL (0);
#ifdef _BUFFY_H
int mutt_monitor_add (BUFFY *b);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment