From: Henrique de Moraes Holschuh <hmh@debian.org>
Subject: Shutdown and close sockets cleanly

Origin: vendor, Debian Cyrus IMAPd 2.1.4-11 (2002-05-19)

Cleanly shutdown and close sockets, this is supposed to allow for better
TCP teardown on the remote end, and reduces CLOSE_WAIT time.

This patch was written 8 years ago, it is possible that nowadays nothing
will benefit from a shutdown() right before close().  The commit log
from eight years ago mentions that SHUT_RD should be upgraded to
SHUT_RDWR where possible, but only after verification that this is not
going to cause problems (e.g. by discarding data still on flight to the
remote).

Also, it is possible that new daemons and utils in Cyrus 2.2 and 2.3 may
need similar patches.

--- a/imap/backend.c
+++ b/imap/backend.c
@@ -554,6 +554,7 @@ struct backend *backend_connect(struct b
 	    syslog(LOG_ERR, "couldn't authenticate to backend server: %s",
 		   sasl_errstring(r, NULL, NULL));
 	    if (!ret_backend) free(ret);
+ 	    shutdown(sock, SHUT_RDWR);
 	    close(sock);
 	    ret = NULL;
 	}
--- a/imap/fud.c
+++ b/imap/fud.c
@@ -163,6 +163,15 @@ void shut_down(int code)
     mboxlist_done();
     closelog();
     cyrus_done();
+
+    /* be nice to remote */
+    shutdown(0, SHUT_RD);
+    shutdown(1, SHUT_RD);
+    shutdown(2, SHUT_RD);
+    close(0);
+    close(1);
+    close(2);
+
     exit(code);
 }
 
--- a/imap/imapd.c
+++ b/imap/imapd.c
@@ -1057,6 +1057,10 @@ void shut_down(int code)
 #ifdef HAVE_SSL
     tls_shutdown_serverengine();
 #endif
+    /* shutdown socket nicely */
+    cyrus_close_sock(0);
+    cyrus_close_sock(1);
+    cyrus_close_sock(2);
 
     cyrus_done();
 
--- a/imap/lmtpd.c
+++ b/imap/lmtpd.c
@@ -977,6 +977,9 @@ void shut_down(int code)
 
     cyrus_done();
 
+    /* shutdown socket nicely */
+    cyrus_reset_stdio();
+
     exit(code);
 }
 
--- a/imap/pop3d.c
+++ b/imap/pop3d.c
@@ -689,6 +689,9 @@ void shut_down(int code)
 #endif
 
     cyrus_done();
+    cyrus_close_sock(0);
+    cyrus_close_sock(1);
+    cyrus_close_sock(2);
 
     exit(code);
 }
