commit d34a9b7468bc53b4a55d1b553676ba3ba5638c35
Author: Oswald Buddenhagen <[email protected]>
Date: Sat Aug 25 15:29:16 2012 +0200
deal with concurrent maildir modifications during listing
files may be renamed (due to new -> cur transition or flag changes),
which may lead to two effects if ignored:
- we see both the old and the new name, so we report a spurious
duplicate UID
- we see neither name, so we report a spurious deletion
as countermeasure, record and compare directory modification times. upon
mismatch, we just start over - as usual.
src/drv_maildir.c | 38 ++++++++++++++++++++++++++++++++++++++
src/isync.h | 1 +
src/main.c | 3 +++
src/run-tests.pl | 2 +-
4 files changed, 43 insertions(+), 1 deletions(-)
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 9d4a00e..24aae2d 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -507,6 +507,7 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
#endif /* USE_DB */
msg_t *entry;
int i, j, uid, bl, fnl, ret;
+ time_t now, stamps[2];
struct stat st;
char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX];
@@ -536,11 +537,32 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
}
#endif /* USE_DB */
bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", ctx->gen.path );
+ restat:
+ now = time( 0 );
+ for (i = 0; i < 2; i++) {
+ memcpy( buf + bl, subdirs[i], 4 );
+ if (stat( buf, &st )) {
+ sys_error( "Maildir error: cannot stat %s", buf
);
+ goto dfail;
+ }
+ if (st.st_mtime == now && !(DFlags & ZERODELAY)) {
+ /* If the modification happened during this
second, we wouldn't be able to
+ * tell if there were further modifications
during this second. So wait.
+ * This has the nice side effect that we wait
for "batches" of changes to
+ * complete. On the downside, it can
potentially block indefinitely. */
+ info( "Maildir notice: sleeping due to recent
directory modification.\n" );
+ sleep( 1 ); /* FIXME: should make this async */
+ goto restat;
+ }
+ stamps[i] = st.st_mtime;
+ }
for (i = 0; i < 2; i++) {
memcpy( buf + bl, subdirs[i], 4 );
if (!(d = opendir( buf ))) {
sys_error( "Maildir error: cannot list %s", buf
);
+ rfail:
maildir_free_scan( msglist );
+ dfail:
#ifdef USE_DB
if (ctx->db)
tdb->close( tdb, 0 );
@@ -600,6 +622,22 @@ maildir_scan( maildir_store_t *ctx, msglist_t *msglist )
}
closedir( d );
}
+ for (i = 0; i < 2; i++) {
+ memcpy( buf + bl, subdirs[i], 4 );
+ if (stat( buf, &st )) {
+ sys_error( "Maildir error: cannot re-stat %s",
buf );
+ goto rfail;
+ }
+ if (st.st_mtime != stamps[i]) {
+ /* Somebody messed with the mailbox since we
started listing it. */
+#ifdef USE_DB
+ if (ctx->db)
+ tdb->close( tdb, 0 );
+#endif /* USE_DB */
+ maildir_free_scan( msglist );
+ goto again;
+ }
+ }
#ifdef USE_DB
if (ctx->db) {
if ((ret = ctx->db->cursor( ctx->db, 0, &dbc, 0 )))
diff --git a/src/isync.h b/src/isync.h
index fa7d082..a39ab21 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -395,6 +395,7 @@ void cram( const char *challenge, const char *user, const
char *pass,
#define QUIET 8
#define VERYQUIET 16
#define KEEPJOURNAL 32
+#define ZERODELAY 64
extern int DFlags;
diff --git a/src/main.c b/src/main.c
index 85e3699..71470e6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -437,6 +437,9 @@ main( int argc, char **argv )
case 'J':
DFlags |= KEEPJOURNAL;
break;
+ case 'Z':
+ DFlags |= ZERODELAY;
+ break;
case 'v':
version();
case 'h':
diff --git a/src/run-tests.pl b/src/run-tests.pl
index f2b4736..842e6e6 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -282,7 +282,7 @@ sub killcfg()
sub runsync($)
{
# open FILE, "valgrind -q --log-fd=3 ../mbsync ".shift()." -c .mbsyncrc
test 3>&2 2>&1 |";
- open FILE, "../mbsync -D ".shift()." -c .mbsyncrc test 2>&1 |";
+ open FILE, "../mbsync -D -Z ".shift()." -c .mbsyncrc test 2>&1 |";
my @out = <FILE>;
close FILE or push(@out, $! ? "*** error closing mbsync: $!\n" : "***
mbsync exited with signal ".($?&127).", code ".($?>>8)."\n");
return $?, @out;
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel