From: Henrique de Moraes Holschuh <hmh@debian.org>
Subject: Allow user to set the delay before master forgets dead children

Origin: vendor, Debian Cyrus IMAPd 2.1.16-7 (2004-08-07)

* Allows tunning of the amount of time Cyrus master will remember dead
  children ("janitor mourning time"), which can be useful when messages
  are being delayed by extreme system load (use -J to increase the
  default time of two seconds to something large enough to get the
  messages), or there is way too much child churn to wait that long (use
  -J to decrease mourning time to 1s).

  Setting it to 0 would cause us to free the child PID as soon as possible.
  Should the kernel decide to delay delivering the child control messages
  and we process the SIGCHLD *and* do a janitor sweep before the messages
  arrive, it would trigger the process accounting bug described in the
  13d-master-process-handling patch.
  
  This option was added to help tune master on systems which are hitting
  the kind of crap described by Jules Agee (see the description in patch
  13d-master-process-handling).

NOTE: patch is missing manpage fixes to describe -J

--- a/master/master.c
+++ b/master/master.c
@@ -176,6 +176,8 @@ struct centry {
 static struct centry *ctable[child_table_size];
 static struct centry *cfreelist;
 
+static int child_mourning_time = 2;    /* Time in seconds to remember child
+					  after processing SIGCHLD */
 static int janitor_frequency = 1;	/* Janitor sweeps per second */
 static int janitor_position;		/* Entry to begin at in next sweep */
 static struct timeval janitor_mark;	/* Last time janitor did a sweep */
@@ -918,7 +920,7 @@ void reap_child(void)
 		}
 	    }
 	    c->service_state = SERVICE_STATE_DEAD;
-	    c->janitor_deadline = time(NULL) + 2;
+	    c->janitor_deadline = time(NULL) + child_mourning_time;
 	} else {
 	    /* Are we multithreaded now? we don't know this child */
 	    syslog(LOG_ERR,
@@ -1763,9 +1765,9 @@ int main(int argc, char **argv)
     p = getenv("CYRUS_VERBOSE");
     if (p) verbose = atoi(p) + 1;
 #ifdef HAVE_NETSNMP
-    while ((opt = getopt(argc, argv, "C:M:p:l:Ddj:P:x:")) != EOF) {
+    while ((opt = getopt(argc, argv, "C:M:p:l:Ddj:J:P:x:")) != EOF) {
 #else
-    while ((opt = getopt(argc, argv, "C:M:p:l:Ddj:")) != EOF) {
+    while ((opt = getopt(argc, argv, "C:M:p:l:Ddj:J:")) != EOF) {
 #endif
 	switch (opt) {
 	case 'C': /* alt imapd.conf file */
@@ -1798,8 +1800,15 @@ int main(int argc, char **argv)
 	    /* Janitor frequency */
 	    janitor_frequency = atoi(optarg);
 	    if(janitor_frequency < 1)
-		fatal("The janitor period must be at least 1 second", EX_CONFIG);
+		fatal("The janitor frequency must be at least once per second", EX_CONFIG);
 	    break;   
+       case 'J':
+           /* Janitor delay before cleanup of a child */
+           child_mourning_time = atoi(optarg);
+           if(child_mourning_time < 1)
+               fatal("The janitor's mourning time interval must be at least 1 second",
+                       EX_CONFIG);
+           break;
 #ifdef HAVE_NETSNMP
 	case 'P': /* snmp AgentXPingInterval */
 	    agentxpinginterval = atoi(optarg);
