#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
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.
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;
#include "mx.h"
int MonitorFilesChanged;
+int MonitorContextChanged;
struct Monitor
{
static size_t PollFdsLen = 0;
static struct pollfd *PollFds;
+static int MonitorContextDescriptor = -1;
+
struct MonitorInfo
{
short magic;
static int monitor_handle_ignore(int desc)
{
- int new_descr = -1;
+ int new_desc = -1;
struct Monitor *iter = Monitor;
struct stat sb;
{
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",
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
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)
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;
}
}
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) ||
}
mutt_debug(3, "inotify_add_watch descriptor=%d for '%s'\n", desc, info.path);
+ if (!mailbox)
+ MonitorContextDescriptor = desc;
+
monitor_create(&info, desc);
return 0;
}
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;