Tabor J. Wells writes ("Re: [EXIM] Serializing local delivery to a
procmail pipe"):
....
> But that's the problem right now. Procmail is creating so many locks that
> they all just thrash the system waiting on release. The volume of bounces
> is such that quickly there are thousands of processes spawned which are
> piped to procmail which create a lock and spin waiting for it to be
> released. Is there any possibility of adding a serialize option for the
> transport in a future version? Or barring that modelling something like
> the smtp_accept_queue_per_connection option?
Surely your real problem is that procmail isn't doing locking properly
(with fcntl F_SETLKW) and instead is polling on a lockfile ?
If so, the following small C program may be of some help. Try
something like
"|with-lock-ex -w /path/to/lockfile program arg arg ..."
in the appropriate Exim aliasfile or wherever.
Better would be to fix (or reconfigure) procmail, of course.
Ian.
/*
* File locker
*
* Usage: with-lock-ex -<mode> <lockfile> <command> <args>...
*
* modes are
* w wait for the lock
* f fail if the lock cannot be acquired
* q silently do nothing if the lock cannot be acquired
*
* with-lock-ex will open and lock the lockfile for writing and
* then feed the remainder of its arguments to exec(2); when
* that process terminates the fd will be closed and the file
* unlocked automatically by the kernel.
*
* If invoked as with-lock, behaves like with-lock-ex -f (for backward
* compatibility with an earlier version).
*
* This file written by me, Ian Jackson, in 1993, 1994, 1995, 1996,
* 1998, 1999. I hereby place it in the public domain.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
static const char *cmd;
static void fail(const char *why) __attribute__((noreturn));
static void fail(const char *why) {
fprintf(stderr,"with-lock-ex %s: %s: %s\n",cmd,why,strerror(errno));
exit(255);
}
int main(int argc, char **argv) {
int fd, mode, um;
long cloexec;
struct flock fl;
const char *p;
if (argc >= 3 && !strcmp((p= strrchr(argv[0],'/')) ? ++p : argv[0], "with-lock")) {
mode= 'f';
} else if (argc < 4 || argv[1][0] != '-' || argv[1][2] ||
((mode= argv[1][1]) != 'w' && mode != 'q' && mode != 'f')) {
fputs("usage: with-lock-ex -w|-q|-f <lockfile> <command> <args>...\n"
" with-lock <lockfile> <command> <args>...\n",
stderr);
exit(255);
} else {
argv++; argc--;
}
cmd= argv[2];
um= umask(0777); if (um==-1) fail("find umask");
if (umask(um)==-1) fail("reset umask");
fd= open(argv[1],O_RDWR|O_CREAT,0666&~(um|((um&0222)<<1))); if (fd<0) fail(argv[1]);
for (;;) {
fl.l_type= F_WRLCK;
fl.l_whence= SEEK_SET;
fl.l_start= 0;
fl.l_len= 1;
if (fcntl(fd, mode=='w' ? F_SETLKW : F_SETLK, &fl) != -1) break;
if (mode=='q' && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EBUSY)) exit(0);
if (errno != EINTR) fail("could not acquire lock");
}
cloexec= fcntl(fd, F_GETFD); if (cloexec==-1) fail("fcntl F_GETFD");
cloexec &= ~1;
if (fcntl(fd, F_SETFD, cloexec)==-1) fail("fcntl F_SETFD");
execvp(cmd,argv+2);
fail("unable to execute command");
}
--
*** Exim information can be found at
http://www.exim.org/ ***