aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2001-07-01 16:19:04 +0000
committerEric S. Raymond <esr@thyrsus.com>2001-07-01 16:19:04 +0000
commitd9a79d4bc51b408cd3de5161fa318c7140ef4369 (patch)
tree1b862f87497edd7d52104c5b45ee3adb191a80d6
parent52c4509bc72fd0627e3104e11e8750fbb1fc5b48 (diff)
downloadfetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.tar.gz
fetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.tar.bz2
fetchmail-d9a79d4bc51b408cd3de5161fa318c7140ef4369.zip
Fix for zombie problem.
svn path=/trunk/; revision=3387
-rw-r--r--NEWS2
-rw-r--r--fetchmail.man7
-rw-r--r--sink.c48
3 files changed, 56 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index e719a2df..b3fe4dc7 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@
(The `lines' figures total .c, .h, .l, and .y files under version control.)
+* Signal-processing fix for Debian bug #102711.
+
fetchmail-5.8.10 (Mon Jun 25 17:04:08 EDT 2001), 20922 lines:
* More fixes for the new message-marking code from Thomas Moestl.
diff --git a/fetchmail.man b/fetchmail.man
index 73ebd39d..0e84e134 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -2107,6 +2107,13 @@ in foreground while a background fetchmail is running will do
whichever of these is appropriate to wake it up.
.SH BUGS AND KNOWN PROBLEMS
+The mda and plugin options interact badly. In order to collect error
+status from the MDA, fetchmail has to change its normal signal
+handling so that dead plugin processes don't get reaped until the end
+of the poll cycle. This can cause resource starvation if too many
+zombies accumulate. So either don't deliver to a MDA using plugins or
+risk being overrun by an army of undead.
+.PP
The RFC822 address parser used in multidrop mode chokes on some
@-addresses that are technically legal but bizarre. Strange uses of
quoting and embedded comments are likely to confuse it.
diff --git a/sink.c b/sink.c
index 151554a9..3e55b89a 100644
--- a/sink.c
+++ b/sink.c
@@ -14,23 +14,35 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <signal.h>
+#include <time.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif /* HAVE_MEMORY_H */
#if defined(STDC_HEADERS)
#include <stdlib.h>
#endif
#if defined(HAVE_UNISTD_H)
-#include <unistd.h>
+#include <unistd.h>
#endif
#if defined(HAVE_STDARG_H)
#include <stdarg.h>
#else
#include <varargs.h>
#endif
+#include <ctype.h>
+#include <time.h>
#include "fetchmail.h"
#include "socket.h"
#include "smtp.h"
#include "i18n.h"
+/* BSD portability hack...I know, this is an ugly place to put it */
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
/* makes the open_sink()/close_sink() pair non-reentrant */
static int lmtp_responses;
@@ -164,6 +176,11 @@ int smtp_open(struct query *ctl)
/* these are shared by open_sink and stuffline */
static FILE *sinkfp;
+#ifndef HAVE_SIGACTION
+static RETSIGTYPE (*sigchld)(int);
+#else
+static struct sigaction sa_old;
+#endif /* HAVE_SIGACTION */
int stuffline(struct query *ctl, char *buf)
/* ship a line to the given control block's output sink (SMTP server or MDA) */
@@ -491,6 +508,9 @@ int open_sink(struct query *ctl, struct msgblk *msg,
/* set up sinkfp to be an input sink we can ship a message to */
{
struct idlist *idp;
+#ifdef HAVE_SIGACTION
+ struct sigaction sa_new;
+#endif /* HAVE_SIGACTION */
*bad_addresses = *good_addresses = 0;
@@ -915,6 +935,20 @@ int open_sink(struct query *ctl, struct msgblk *msg,
report(stderr, _("MDA open failed\n"));
return(PS_IOERR);
}
+
+ /*
+ * We need to disable the normal SIGCHLD handling here because
+ * sigchld_handler() would reap away the error status, returning
+ * error status instead of 0 for successful completion.
+ */
+#ifndef HAVE_SIGACTION
+ sigchld = signal(SIGCHLD, SIG_DFL);
+#else
+ memset (&sa_new, 0, sizeof sa_new);
+ sigemptyset (&sa_new.sa_mask);
+ sa_new.sa_handler = SIG_DFL;
+ sigaction (SIGCHLD, &sa_new, &sa_old);
+#endif /* HAVE_SIGACTION */
}
/*
@@ -938,6 +972,12 @@ void release_sink(struct query *ctl)
pclose(sinkfp);
sinkfp = (FILE *)NULL;
}
+#ifndef HAVE_SIGACTION
+ signal(SIGCHLD, sigchld);
+#else
+ sigaction (SIGCHLD, &sa_old, NULL);
+#endif /* HAVE_SIGACTION */
+ deal_with_sigchld();
}
}
@@ -956,6 +996,12 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)
}
else
rc = 0;
+#ifndef HAVE_SIGACTION
+ signal(SIGCHLD, sigchld);
+#else
+ sigaction (SIGCHLD, &sa_old, NULL);
+#endif /* HAVE_SIGACTION */
+ deal_with_sigchld();
if (rc)
{
report(stderr,