|
1 Source: In-House |
|
2 Reason: Solaris leave socket in TIME_WAIT status |
|
3 Reasonable to upstream?: Not much for Linux. |
|
4 |
|
5 Note: This patch do not look "pretty" but its code |
|
6 is re-used from the original patch which colided |
|
7 with the proftpd-1.3.6 code. During proftpd update |
|
8 the binaries were tested on huge # of small files |
|
9 (!passive) it looked good so the original patch was |
|
10 removed. |
|
11 Now it has returned as regression from supercluster |
|
12 testing. |
|
13 Final fix of this problem on Solaris will need further |
|
14 discussion with community then it will be probably fixed |
|
15 by a proftpd update. |
|
16 |
|
17 --- a//src/data.c 2016-03-10 17:04:32.000000000 -0800 |
|
18 +++ b/src/data.c 2016-06-23 05:41:37.547107933 -0700 |
|
19 @@ -337,6 +337,7 @@ |
|
20 static int data_active_open(char *reason, off_t size) { |
|
21 conn_t *c; |
|
22 int bind_port, rev; |
|
23 + int retries = 0; |
|
24 pr_netaddr_t *bind_addr; |
|
25 unsigned char *root_revoke = NULL; |
|
26 |
|
27 @@ -384,6 +385,7 @@ |
|
28 } |
|
29 } |
|
30 |
|
31 + for(;;) { /* begin of endless loop */ |
|
32 session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE); |
|
33 if (session.d == NULL) { |
|
34 int xerrno = errno; |
|
35 @@ -425,7 +427,7 @@ |
|
36 pr_inet_set_socket_opts(session.d->pool, session.d, |
|
37 (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0, |
|
38 main_server->tcp_keepalive); |
|
39 - |
|
40 + |
|
41 } else { |
|
42 pr_inet_set_socket_opts(session.d->pool, session.d, |
|
43 0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0), |
|
44 @@ -442,6 +444,13 @@ |
|
45 |
|
46 if (pr_inet_connect(session.d->pool, session.d, &session.data_addr, |
|
47 session.data_port) == -1) { |
|
48 + if (session.d->xerrno == EADDRINUSE && retries < 16) { |
|
49 + destroy_pool(session.d->pool); |
|
50 + pr_signals_handle(); |
|
51 + /* Wait up to MSL to avoid TIME_WAIT. */ |
|
52 + sleep(retries++); |
|
53 + continue; /* continue in endless loop */ |
|
54 + } |
|
55 pr_log_debug(DEBUG6, |
|
56 "Error connecting to %s#%u for active data transfer: %s", |
|
57 pr_netaddr_get_ipstr(&session.data_addr), session.data_port, |
|
58 @@ -453,7 +462,8 @@ |
|
59 destroy_pool(session.d->pool); |
|
60 session.d = NULL; |
|
61 return -1; |
|
62 - } |
|
63 + } else break; /* finish the endless loop */ |
|
64 + } /* end of endless loop */ |
|
65 |
|
66 c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA, |
|
67 session.d->listen_fd, -1, -1, TRUE); |