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: 2019-10-25~668^2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5381b665dd6daab4422c8a9af1b009ebef3f6f7a;p=neomutt 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/maildir/mh.c b/maildir/mh.c index b106ba172..4ecf442b2 100644 --- a/maildir/mh.c +++ b/maildir/mh.c @@ -64,6 +64,9 @@ #ifdef USE_HCACHE #include "hcache/hcache.h" #endif +#ifdef USE_INOTIFY +#include "monitor.h" +#endif /* These Config Variables are only used in maildir/mh.c */ bool CheckNew; ///< Config: (maildir,mh) Check for new mail while the mailbox is open @@ -2348,9 +2351,21 @@ static int maildir_mbox_check(struct 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. @@ -2516,8 +2531,21 @@ static int mh_mbox_check(struct 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); + } md = NULL; last = &md; diff --git a/monitor.c b/monitor.c index 48b5c7960..620b5e5a7 100644 --- a/monitor.c +++ b/monitor.c @@ -41,6 +41,7 @@ #include "mx.h" int MonitorFilesChanged; +int MonitorContextChanged; struct Monitor { @@ -58,6 +59,8 @@ static size_t PollFdsCount = 0; static size_t PollFdsLen = 0; static struct pollfd *PollFds; +static int MonitorContextDescriptor = -1; + struct MonitorInfo { short magic; @@ -174,7 +177,7 @@ static void monitor_delete(struct Monitor *monitor) static int monitor_handle_ignore(int desc) { - int new_descr = -1; + int new_desc = -1; struct Monitor *iter = Monitor; struct stat sb; @@ -185,7 +188,7 @@ static int monitor_handle_ignore(int desc) { if (iter->magic == MUTT_MH && stat(iter->mh_backup_path, &sb) == 0) { - if ((new_descr = inotify_add_watch(INotifyFd, iter->mh_backup_path, + if ((new_desc = inotify_add_watch(INotifyFd, iter->mh_backup_path, INOTIFY_MASK_FILE)) == -1) { mutt_debug(2, "inotify_add_watch failed for '%s', errno=%d %s\n", @@ -196,7 +199,7 @@ static int monitor_handle_ignore(int desc) mutt_debug(3, "inotify_add_watch descriptor=%d for '%s'\n", desc, iter->mh_backup_path); iter->st_dev = sb.st_dev; iter->st_ino = sb.st_ino; - iter->desc = new_descr; + iter->desc = new_desc; } } else @@ -204,14 +207,17 @@ static int monitor_handle_ignore(int desc) mutt_debug(3, "cleanup watch (implicitely removed) - descriptor=%d\n", desc); } - if (new_descr == -1) + if (MonitorContextDescriptor == desc) + MonitorContextDescriptor = new_desc; + + if (new_desc == -1) { monitor_delete(iter); monitor_check_free(); } } - return new_descr; + return new_desc; } #define EVENT_BUFLEN MAX(4096, sizeof(struct inotify_event) + NAME_MAX + 1) @@ -285,6 +291,8 @@ int mutt_monitor_poll(void) 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; } } @@ -384,7 +392,11 @@ int mutt_monitor_add(struct Mailbox *mailbox) desc = monitor_resolve(&info, mailbox); if (desc != RESOLVERES_OK_NOTEXISTING) + { + if (!mailbox && (desc == RESOLVERES_OK_EXISTING)) + MonitorContextDescriptor = info.monitor->desc; return desc == RESOLVERES_OK_EXISTING ? 0 : -1; + } mask = info.isdir ? INOTIFY_MASK_DIR : INOTIFY_MASK_FILE; if ((INotifyFd == -1 && monitor_init() == -1) || @@ -396,6 +408,9 @@ int mutt_monitor_add(struct Mailbox *mailbox) } mutt_debug(3, "inotify_add_watch descriptor=%d for '%s'\n", desc, info.path); + if (!mailbox) + MonitorContextDescriptor = desc; + monitor_create(&info, desc); return 0; } @@ -433,6 +448,9 @@ int mutt_monitor_remove(struct Mailbox *mailbox) mutt_debug(3, "inotify_rm_watch for '%s' descriptor=%d\n", info.path, info.monitor->desc); + if (!mailbox && (MonitorContextDescriptor == info.monitor->desc)) + MonitorContextDescriptor = -1; + monitor_delete(info.monitor); monitor_check_free(); return 0; diff --git a/monitor.h b/monitor.h index 1159abe07..fb11feef8 100644 --- a/monitor.h +++ b/monitor.h @@ -24,6 +24,7 @@ #define _MUTT_MONITOR_H extern int MonitorFilesChanged; +extern int MonitorContextChanged; struct Mailbox;