components/proftpd/patches/004.proftpd-retry.patch
changeset 6413 3d1d422367d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/004.proftpd-retry.patch	Thu Jun 23 06:21:51 2016 -0700
@@ -0,0 +1,67 @@
+Source: In-House
+Reason: Solaris leave socket in TIME_WAIT status
+Reasonable to upstream?: Not much for Linux.
+
+Note: This patch do not look "pretty" but its code
+is re-used from the original patch which colided
+with the proftpd-1.3.6 code. During proftpd update
+the binaries were tested on huge # of small files
+(!passive) it looked good so the original patch was
+removed.
+Now it has returned as regression from supercluster
+testing.
+Final fix of this problem on Solaris will need further
+discussion with community then it will be probably fixed
+by a proftpd update.
+
+--- a//src/data.c	2016-03-10 17:04:32.000000000 -0800
++++ b/src/data.c	2016-06-23 05:41:37.547107933 -0700
+@@ -337,6 +337,7 @@
+ static int data_active_open(char *reason, off_t size) {
+   conn_t *c;
+   int bind_port, rev;
++  int retries = 0;
+   pr_netaddr_t *bind_addr;
+   unsigned char *root_revoke = NULL;
+ 
+@@ -384,6 +385,7 @@
+     }
+   }
+ 
++  for(;;) { /* begin of endless loop */
+   session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);
+   if (session.d == NULL) {
+     int xerrno = errno;
+@@ -425,7 +427,7 @@
+     pr_inet_set_socket_opts(session.d->pool, session.d,
+       (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
+       main_server->tcp_keepalive);
+-    
++
+   } else {
+     pr_inet_set_socket_opts(session.d->pool, session.d,
+       0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
+@@ -442,6 +444,13 @@
+ 
+   if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
+       session.data_port) == -1) {
++    if (session.d->xerrno == EADDRINUSE && retries < 16) {
++      destroy_pool(session.d->pool);
++      pr_signals_handle();
++      /* Wait up to MSL to avoid TIME_WAIT. */
++      sleep(retries++);
++      continue; /* continue in endless loop */
++    }
+     pr_log_debug(DEBUG6,
+       "Error connecting to %s#%u for active data transfer: %s",
+       pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
+@@ -453,7 +462,8 @@
+     destroy_pool(session.d->pool);
+     session.d = NULL;
+     return -1;
+-  }
++  } else break; /* finish the endless loop */
++  } /* end of endless loop */
+ 
+   c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
+     session.d->listen_fd, -1, -1, TRUE);