Re: Mailbox locking
On Tue, Dec 20, 2005 at 03:17:27PM +0200, Niko Tyni wrote:
>while trying to avoid fixing the Mail::Audit bugs, I've run
>into the same mbox locking problem with Email::LocalDelivery.
>Upstream is still using simply flock(LOCK_EX). Debian policy says
>"use fcntl() first and dot locking after this".
>Using fcntl() locks from Perl seems a bit tricky, since I'll have to
>pack() the lock argument together myself. I need some advice here.
>The corresponding struct in /usr/include/bits/fcntl.h is
> short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
> short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
> __off_t l_start; /* Offset where the lock begins. */
> __off_t l_len; /* Size of the locked area; zero means until EOF. */
> __off64_t l_start; /* Offset where the lock begins. */
> __off64_t l_len; /* Size of the locked area; zero means until EOF. */
> __pid_t l_pid; /* Process holding the lock. */
>I'm a bit worried about the __off64_t stuff. Can I assume that these are
>of the 'l' type for pack()? What about pid_t? The best hit on Google I found,
>my $FLOCK_STRUCT = 's s l l i';
Unfortunately, using pack for the flock struct is rather difficult.
There's no easy way to represent __off64_t using pack the way perl is
currently configured: "q" doesn't work.
Even if it did, you need to take padding into account on some
architectures. Take for example these working templates for powerpc and
$ppc_flock = 's s x4 x4l x4l i';
$i386_flock = 's s lx4 lx4 i';
note that on powerpc l_start is padded to an 8 byte boundary. These are
also limited to positive 32bit values for l_start/l_len. Ick.
A better option if you need to use fcntl locking is to write an XS
>The dotlocking part is easy to do by execing dotlockfile(1) from liblockfile1;
>it can't be done inside the module because it needs setgid mail privileges.
I took a look at maillock() from liblockfile1, which is recommended by policy,
thinking to create an XS module for that interface.
Interestingly, that library doesn't use fcntl locking at all. It also
calls dotlockfile to do the actual locking in cases where the directory
is not writable by the current user, but is writable by group mail.
If you want to build a module linked to liblockfile1, you may care to
look at this prototype: http://people.debian.org/~bod/Lock.tar.gz .
Requires a better module name, documentation etc, but it does work:
my $lock = Lock->new('/var/mail/bod.lock');
Unlocks automatically on destruction if $lock->unlock was not explicitly
Feel free to steal all/any/none of that code unattributed as you wish.