7095498 Unable to build data connection: Address already in use
authorMilan Jurik <Milan.Jurik@oracle.com>
Mon, 31 Oct 2011 03:15:38 -0700
changeset 554 0ed48135019d
parent 553 29d0b0e1eaef
child 555 f8fe8d6e1917
7095498 Unable to build data connection: Address already in use
components/proftpd/patches/proftpd-retry.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/proftpd/patches/proftpd-retry.patch	Mon Oct 31 03:15:38 2011 -0700
@@ -0,0 +1,85 @@
+--- proftpd-1.3.3e/src/data.c	Thu Mar  3 09:10:03 2011
++++ proftpd-1.3.3e/src/data.c	Wed Oct  5 08:07:57 2011
[email protected]@ -337,44 +337,55 @@
+ static int data_active_open(char *reason, off_t size) {
+   conn_t *c;
+   int rev;
++  int retries = 0;
+ 
+   if (!reason && session.xfer.filename)
+     reason = session.xfer.filename;
+ 
+-  session.d = pr_inet_create_conn(session.pool, NULL, -1,
+-    session.c->local_addr, session.c->local_port-1, TRUE);
++  for (;;) {
++    session.d = pr_inet_create_conn(session.pool, NULL, -1,
++      session.c->local_addr, session.c->local_port-1, TRUE);
+ 
+-  /* Set the "stalled" timer, if any, to prevent the connection
+-   * open from taking too long
+-   */
+-  if (timeout_stalled)
+-    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
+-      "TimeoutStalled");
++    /* Set the "stalled" timer, if any, to prevent the connection
++     * open from taking too long
++     */
++    if (timeout_stalled)
++      pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
++        "TimeoutStalled");
+ 
+-  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
++    rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);
+ 
+-  /* Protocol and socket options should be set before handshaking. */
++    /* Protocol and socket options should be set before handshaking. */
+ 
+-  if (session.xfer.direction == PR_NETIO_IO_RD) {
+-    pr_inet_set_socket_opts(session.d->pool, session.d,
+-      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
+-    pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
+-      0, 1, 1);
++    if (session.xfer.direction == PR_NETIO_IO_RD) {
++      pr_inet_set_socket_opts(session.d->pool, session.d,
++        (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
++      pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
++        0, 1, 1);
+     
+-  } else {
+-    pr_inet_set_socket_opts(session.d->pool, session.d,
+-      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
+-    pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
+-      0, 1, 1);
+-  }
++    } else {
++      pr_inet_set_socket_opts(session.d->pool, session.d,
++        0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
++      pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
++        0, 1, 1);
++    }
+ 
+-  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
++    if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
+       session.data_port) == -1) {
+-    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
+-      strerror(session.d->xerrno));
+-    destroy_pool(session.d->pool);
+-    session.d = NULL;
+-    return -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;
++      }
++      pr_response_add_err(R_425, _("Unable to build data connection: %s"),
++        strerror(session.d->xerrno));
++      destroy_pool(session.d->pool);
++      session.d = NULL;
++      return -1;
++    } else
++      break;
+   }
+ 
+   c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,