Your message dated Mon, 27 Oct 2008 11:24:01 -0500
with message-id <[EMAIL PROTECTED]>
and subject line Fixed in 1.03-46
has caused the Debian Bug report #466447,
regarding qmail-local maildir delivery race condition
to be marked as done.
This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.
(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [EMAIL PROTECTED]
immediately.)
--
466447: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=466447
Debian Bug Tracking System
Contact [EMAIL PROTECTED] with problems
--- Begin Message ---
Package: qmail-src
Version: 1.03-45
Severity: important
I just started getting MANY complaints about duplicate e-mail delivery
from IMAP users. Upon investigation, it turns out that Dan Bernstein
doesn't obey his own rules about manipulating Maildirs.
To be precise, qmail-local was doing:
8945 link("tmp/1203363108.8945.science", "new/1203363108.8945.science") = 0
8945 open("new/1203363108.8945.science", O_RDONLY) = -1 ENOENT (No such file
or directory)
8945 unlink("tmp/1203363108.8945.science") = 0
8945 exit_group(1) = ?
This is because dovecot is using inotify to get instant notice of
the file's appearance and yanking the file out of new into cur before
qmail-local can open it to verify that it was copied.
Thus qmail-local returns 111 (temporary delivery failure), and local delivery
is retried... quite a few times before qmail-local wins the race.
It's a narrow race, but it's been a latent bug since forever.
Once the file is linked into new/, it's the proprty of the MUA, and
the MTA can make no further assumptions about what will happen to it.
The problem is in the maildir_child() function and can be neatly avoided
by deleting the if() containing the last open() at the end of that function.
I'm not entirely sure why it's there. If the goal is to ensure the link()
call hits the disk, on Linux that's done by opening and fsync()ing the
DIRECTORY, not the file. Alternatively, you can just ignore a failure
to open. I.e. replace
if ((fd = open(fnnewtph, O_RDONLY)) < 0 ||
fsync(fd) < 0 || close(fd) < 0) goto fail;
by
if ((fd = open(fnnewtph, O_RDONLY)) >= 0)
{
fsync(fd);
close(fd);
}
If you need to check that the link happened, the race can be widened by
stat()ing the tmp/ file and verifying its link count, but really, the
code shouldn't do anything.
--- End Message ---
--- Begin Message ---
See changelog for details.
Cheers!
Jon
--- End Message ---