From: Kevin McCarthy Date: Tue, 26 Jun 2018 00:54:43 +0000 (-0700) Subject: Work around open mailbox monitor code check issue. X-Git-Tag: mutt-1-11-rel~129 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=550771fd49e439b4fb5551ade98ad034bb57fabb;p=mutt 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. --- diff --git a/mh.c b/mh.c index a48dd832..cda81fe8 100644 --- a/mh.c +++ b/mh.c @@ -37,6 +37,9 @@ #endif #include "mutt_curses.h" #include "buffy.h" +#ifdef USE_INOTIFY +#include "monitor.h" +#endif #include #include @@ -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)); diff --git a/monitor.c b/monitor.c index 7979897a..da9afc69 100644 --- a/monitor.c +++ b/monitor.c @@ -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; diff --git a/monitor.h b/monitor.h index cd4918b2..3f21413d 100644 --- a/monitor.h +++ b/monitor.h @@ -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);