]> Pileus Git - ~andy/fetchmail/commitdiff
Fix for zombie problem.
authorEric S. Raymond <esr@thyrsus.com>
Sun, 1 Jul 2001 16:19:04 +0000 (16:19 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Sun, 1 Jul 2001 16:19:04 +0000 (16:19 -0000)
svn path=/trunk/; revision=3387

NEWS
fetchmail.man
sink.c

diff --git a/NEWS b/NEWS
index e719a2df9b56cbca0dd1ffe0ced86db2b38758ce..b3fe4dc72b510ab65c8efbce25125160b0079ce1 100644 (file)
--- 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.
index 73ebd39d64b21da498306606a369bf333a91cc88..0e84e13444f1187dc45ec622f4414bf678d2c928 100644 (file)
@@ -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 151554a9ed092ac98b2821be2406d15b271df344..3e55b89a1867581fe8ae768805b3b793d7450f0c 100644 (file)
--- a/sink.c
+++ b/sink.c
 #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,