Skip to content

Commit

Permalink
mod_proxy: Keep connection alive on addressTTL expiry if the DNS didn…
Browse files Browse the repository at this point in the history
…'t change.

* modules/proxy/proxy_util.c(address_cleanup):
  Rename to conn_cleanup() since it also closes the socket, and run
  socket_cleanup() first to avoid dangling conn->sock->remote_addr.

* modules/proxy/proxy_util.c(ap_proxy_determine_address):
  Compare the new address with the old one and keep the socket alive
  if it did not change.

Follow up to r1918410.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1918412 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
ylavic committed Jun 19, 2024
1 parent 5ea9b73 commit 9b8546a
Showing 1 changed file with 38 additions and 20 deletions.
58 changes: 38 additions & 20 deletions modules/proxy/proxy_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1512,8 +1512,9 @@ static void socket_cleanup(proxy_conn_rec *conn)
apr_pool_clear(conn->scpool);
}

static void address_cleanup(proxy_conn_rec *conn)
static void conn_cleanup(proxy_conn_rec *conn)
{
socket_cleanup(conn);
conn->address = NULL;
conn->addr = NULL;
conn->hostname = NULL;
Expand All @@ -1522,9 +1523,6 @@ static void address_cleanup(proxy_conn_rec *conn)
if (conn->uds_pool) {
apr_pool_clear(conn->uds_pool);
}
if (conn->sock) {
socket_cleanup(conn);
}
}

static apr_status_t conn_pool_cleanup(void *theworker)
Expand Down Expand Up @@ -3009,13 +3007,25 @@ PROXY_DECLARE(apr_status_t) ap_proxy_determine_address(const char *proxy_functio

PROXY_THREAD_UNLOCK(worker);

/* Kill any socket using the old address */
if (conn->sock) {
if (r ? APLOGrdebug(r) : APLOGdebug(s)) {
/* XXX: this requires the old conn->addr[ess] to still
* be alive since it's not copied by apr_socket_connect()
* in ap_proxy_connect_backend().
*/
/* Release the old conn address */
if (conn->address) {
/* conn->address->addr cannot be released while it's used by
* conn->sock->remote_addr, thus if the old address is still
* the one used at apr_socket_connect() time AND the socket
* shouldn't be closed because the newly resolved address is
* the same. In this case let's (re)attach the old address to
* the socket lifetime (scpool), in any other case just release
* it now.
*/
int addr_alive = 0,
conn_alive = (conn->sock && conn->addr &&
proxy_addrs_equal(conn->addr, address->addr));
if (conn_alive) {
apr_sockaddr_t *remote_addr = NULL;
apr_socket_addr_get(&remote_addr, APR_REMOTE, conn->sock);
addr_alive = (conn->addr == remote_addr);
}
else if (conn->sock && (r ? APLOGrdebug(r) : APLOGdebug(s))) {
apr_sockaddr_t *local_addr = NULL;
apr_sockaddr_t *remote_addr = NULL;
apr_socket_addr_get(&local_addr, APR_LOCAL, conn->sock);
Expand All @@ -3033,18 +3043,26 @@ PROXY_DECLARE(apr_status_t) ap_proxy_determine_address(const char *proxy_functio
local_addr, remote_addr);
}
}
socket_cleanup(conn);
if (addr_alive) {
apr_pool_cleanup_kill(conn->pool, conn->address,
proxy_address_cleanup);
apr_pool_cleanup_register(conn->scpool, conn->address,
proxy_address_cleanup,
apr_pool_cleanup_null);
}
else {
apr_pool_cleanup_run(conn->pool, conn->address,
proxy_address_cleanup);
if (!conn_alive) {
conn_cleanup(conn);
}
}
}

/* Kill the old address (if any) and use the new one */
if (conn->address) {
apr_pool_cleanup_run(conn->pool, conn->address,
proxy_address_cleanup);
}
/* Use the new address */
apr_pool_cleanup_register(conn->pool, address,
proxy_address_cleanup,
apr_pool_cleanup_null);
address_cleanup(conn);
conn->address = address;
conn->hostname = address->hostname;
conn->port = address->hostport;
Expand Down Expand Up @@ -3126,7 +3144,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
if (!conn->uds_path || strcmp(conn->uds_path, uds_path) != 0) {
apr_pool_t *pool = conn->pool;
if (conn->uds_path) {
address_cleanup(conn);
conn_cleanup(conn);
if (!conn->uds_pool) {
apr_pool_create(&conn->uds_pool, worker->cp->dns_pool);
}
Expand Down Expand Up @@ -3227,7 +3245,7 @@ ap_proxy_determine_connection(apr_pool_t *p, request_rec *r,
if (conn->hostname
&& (conn->port != hostport
|| ap_cstr_casecmp(conn->hostname, hostname) != 0)) {
address_cleanup(conn);
conn_cleanup(conn);
}

/* Resolve the connection address with the determined hostname/port */
Expand Down

0 comments on commit 9b8546a

Please sign in to comment.