From d9a79d4bc51b408cd3de5161fa318c7140ef4369 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Sun, 1 Jul 2001 16:19:04 +0000 Subject: Fix for zombie problem. svn path=/trunk/; revision=3387 --- NEWS | 2 ++ fetchmail.man | 7 +++++++ sink.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) 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 #include #include +#include +#include +#ifdef HAVE_MEMORY_H +#include +#endif /* HAVE_MEMORY_H */ #if defined(STDC_HEADERS) #include #endif #if defined(HAVE_UNISTD_H) -#include +#include #endif #if defined(HAVE_STDARG_H) #include #else #include #endif +#include +#include #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, -- cgit v1.2.3