Emmanuel Dreyfus <manu@...> wrote:
> A simple way of fixing the issue would just be to issue a TEMPFAIL in
> this situation, which would reflect the real problem: your system cannot
> function proprely because of resource exhaustion, and the sender should
> retry later.
Wait, wait, wait... fopen/fdopen usage is quite limited:
1) dump.c, for duming the database
2) sync.c, for MX sync
3) milter-greylist.c, for the PID file
4) stat.c, for the custom stat output
#3 and #4 are not a problem: it happens on startup and you'll never use
a file descriptor above 256 here
#2 can happen if the MX sync connection breaks during operation
#1 is what Solaris users experience
The TEMPFAIL solution won't help here, but we can make sure we keep a
file descriptor < 256 open for dumps: after a dumps succeeds, we open
/dev/null and use dup2 to associate it to the low file descriptor we
just used. On the next dump, we open the new file, use dup2 and here we
are. I quickly wrote some code for that idea just below (not tested, not
built)
Opinions?
diff -U2 -r1.32 dump.c
--- dump.c 27 Sep 2007 03:47:25 -0000 1.32
+++ dump.c 27 Sep 2007 03:35:02 -0000
@@ -202,6 +202,7 @@
int final;
{
+ static int dumpfd = -1;
+ int newdumpfd;
FILE *dump;
- int dumpfd;
struct timeval tv1, tv2, tv3;
char newdumpfile[MAXPATHLEN + 1];
@@ -234,4 +235,12 @@
}
+ if (dumpfd == -1) {
+ if ((dumpfd = open(_PATH_DEVNULL, O_RDONLY, 0)) == -1) {
+ mg_log(LOG_ERR, "cannot open \"%s\",
+ _PATH_DEVNULL, strerror(errno));
+ exit(EX_OSERR);
+ }
+ }
+
/*
* Dump the database in a temporary file and
@@ -244,12 +253,14 @@
"%s-XXXXXXXX", conf.c_dumpfile);
- if ((dumpfd = mkstemp(newdumpfile)) == -1) {
+ if ((newdumpfd = mkstemp(newdumpfile)) == -1) {
mg_log(LOG_ERR, "mkstemp(\"%s\") failed: %s",
newdumpfile, strerror(errno));
- close(dumpfd);
+ close(newdumpfd);
unlink(newdumpfile); /* clean up ... */
exit(EX_OSERR);
}
+ dumpfd = dup2(newdumpfd, dumpfd);
+
errno = 0;
if ((dump = fdopen(dumpfd, "w")) == NULL) {
@@ -278,4 +289,10 @@
"whitelisted\n#\n", done, greylisted_count,
whitelisted_count);
+ fflush(dump);
+ if ((dumpfd = open(_PATH_DEVNULL, O_RDONLY, 0)) == -1) {
+ mg_log(LOG_ERR, "cannot open \"%s\",
+ _PATH_DEVNULL, strerror(errno));
+ exit(EX_OSERR);
+ }
fclose(dump);
if (s_buffer)
--
Emmanuel Dreyfus
http://hcpnet.free.fr/pubz
manu@...