Samuel Benzaquen wrote:
Hello all,
We've installed clamav / clamav-milter on a sendmail server with HIGH
trafic. It worked well most of the time, but on peak hours (more than 400
concurrent connections per server and 150K mail per hour) the clamav-milter
thorws these errors on the syslog and slows down the process:
May 7 09:27:41 rs25s8 clamav-milter[6926]: ClamAv: thread_create() failed:
11, try again
This is a libmilter error. Specificaly it occurs in listener.c when
libmilter tries to spawn a thread to call the apropriate functions from
your milter.
The CPU never went over 70% (1 Xeon with HT).
The RAM never went over 80% (1 Gb total + 1,5 Gb SWAP)
It just can create the thread!
This is always when it tries to create the 257th concurrent thread of
clamav-milter. When this happens you can see thru 'ps' near 256 threads of
clamav-milter (between 250 and 256, never more).
I'm guessing it is a limit on the kernel/libraries/implementation.
Thaty would be my guess. Why dont you try testing with a null-milter and
see if you get the same results?
The system is a RedHat 7.3, kernel 2.4.20-19.7smp compiled by RedHat,
glibc-2.2.5-43.
We also tried on a Fedora Core 1, kernel 2.6.4 (downloaded and compiled),
glibc-2.3.2-101.1.
Any help would be appreciated,
/*
A Sample Filter
The following sample logs each message to a separate temporary file,
adds a recipient given with the -a flag, and rejects a disallowed
recipient address given with the -r flag. It recognizes the following
options:
-p port The port through which the MTA will connect to the filter.
-t sec The timeout value.
-r addr A recipient to reject.
-a addr A recipient to add.
_
*/
#include sys/types.h
#include sys/stat.h
#include errno.h
#include stdio.h
#include stdlib.h
#include string.h
#include sysexits.h
#include unistd.h
#include syslog.h
#include libmilter/mfapi.h
#ifndef bool
# define bool int
# define TRUE 1
# define FALSE 0
#endif /* ! bool */
struct mlfiPriv
{
char*mlfi_fname;
char*mlfi_connectfrom;
char*mlfi_helofrom;
FILE*mlfi_fp;
};
#define MLFIPRIV((struct mlfiPriv *) smfi_getpriv(ctx))
extern sfsistat mlfi_cleanup(SMFICTX *, bool);
/* recipients to add and reject (set with -a and -r options) */
char *add = NULL;
char *reject = NULL;
sfsistat
mlfi_connect(ctx, hostname, hostaddr)
SMFICTX *ctx;
char *hostname;
_SOCK_ADDR *hostaddr;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_helo(ctx, helohost)
SMFICTX *ctx;
char *helohost;
{
return SMFIS_CONTINUE;
}
sfsistat
mlfi_envfrom(ctx, argv)
SMFICTX *ctx;
char **argv;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_envrcpt(ctx, argv)
SMFICTX *ctx;
char **argv;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_header(ctx, headerf, headerv)
SMFICTX *ctx;
char *headerf;
unsigned char *headerv;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_eoh(ctx)
SMFICTX *ctx;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_body(ctx, bodyp, bodylen)
SMFICTX *ctx;
unsigned char *bodyp;
size_t bodylen;
{
/* continue processing */
return SMFIS_CONTINUE;
}
sfsistat
mlfi_eom(ctx)
SMFICTX *ctx;
{
return SMFIS_ACCEPT;
}
sfsistat
mlfi_abort(ctx)
SMFICTX *ctx;
{
return SMFIS_CONTINUE;
}
sfsistat
mlfi_close(ctx)
SMFICTX *ctx;
{
return SMFIS_CONTINUE;
}
struct smfiDesc smfilter =
{
Null-Milter, /* filter name */
SMFI_VERSION, /* version code -- do not change */
SMFIF_ADDHDRS, /* flags */
mlfi_connect, /* connection info filter */
mlfi_helo, /* SMTP HELO command filter */
mlfi_envfrom, /* envelope sender filter */
mlfi_envrcpt, /* envelope recipient filter */
mlfi_header,/* header filter */
mlfi_eoh, /* end of header */
mlfi_body, /* body block filter */
mlfi_eom, /* end of message */
mlfi_abort, /* message aborted */
mlfi_close, /* connection cleanup */
};
static void
usage(prog)
char *prog;
{
fprintf(stderr,
Usage: %s -p socket-addr [-t timeout]\n,
prog);
}
int
main(argc, argv)
int argc;
char **argv;
{
bool setconn = FALSE;
int c;
const char *args = p:t:h;
extern char *optarg;
/* Process command line options */
while ((c = getopt(argc, argv, args)) != -1)
{
switch (c)
{
case 'p':