fletcher@cs.utexas.edu (Fletcher Mattox) (12/10/90)
My 5.64 runs out of file descriptors when there is lots of mail queued up for a host which has been unreachable for longer than three days (my timeout). It happens to the process running the queue when it tries to return mail to the sender. The senders' addresses all resolve to the same mailer. After it successfully returns mail to several of the senders, it is stopped dead in its tracks with something like this: Dec 8 19:11:32 cs sendmail[16583]: AE16583: SYSERR: queueup: cannot create temp file tfAE16583: Too many open files Anyone know the cause of this?
Craig_Everhart@TRANSARC.COM (12/11/90)
About four months ago, I was distributing a sendmail patch that helped eliminate duplicate messages that would occur when sendmail restarted its work on a given df*/qf* pair before it had finished the previous run (e.g. after a crash). The patch caused sendmail to rewrite the qf* file after each successful delivery. Now, this patch worked fine in 5.61-based sendmails. But in at least 5.64 and beyond, the interface to one of the routines that the patch used (queueup) changed, so that it opens a new file on each call and leaves it open, and the unmodified patch can fail because it didn't know to close any files. If you think that this is the root of your problems, I'll track down the fix to the patched version, which a friend of mine has been running in his configuration with no problems. Hm: it wasn't hard to find. Here's the change, if this was your problem. Down in sendall() in deliver.c, the guts of the checkpoint algorithm is an iterated call to queueup() that looks something like: { int estat; if (DoingMore) queueup(e, TRUE, FALSE, TRUE); DoingMore = FALSE; estat = deliver(e, q); /* Queueup if any delivered */ if (estat == EX_OK) DoingMore = TRUE; } I believe that the thing to do is this: { int estat; FILE *newfile; if (DoingMore) { newfile = queueup(e, TRUE, FALSE, TRUE); if (newfile) { (void) fclose(lockfp); lockfp = newfile; } } DoingMore = FALSE; estat = deliver(e, q); /* Queueup if any delivered */ if (estat == EX_OK) DoingMore = TRUE; } This will call queueup() again, but will correctly close the pointer to the old qf file that it just deleted (replacing it with the newly-written tf file). Good luck. Craig