Skip to content

fix: close the connection before destroying its pool - #22

Open
jarvis9443 wants to merge 1 commit into
masterfrom
fix/close-connection-before-pool-destroy
Open

fix: close the connection before destroying its pool#22
jarvis9443 wants to merge 1 commit into
masterfrom
fix/close-connection-before-pool-destroy

Conversation

@jarvis9443

Copy link
Copy Markdown
Contributor

Problem

ngx_http_multi_upstream_connection_close() destroys c->pool and then calls ngx_close_connection(c):

    if (c->pool) {
        ngx_destroy_pool(c->pool);
    }

    c->destroyed = 1;

    ngx_close_connection(c);

ngx_close_connection() still logs through c->log, and for these upstream connections c->log lives in the pool that was just released. On a debug-enabled build the ngx_log_debug1(..., "reusable connection: %ui") inside ngx_reusable_connection() reads a freed ngx_log_t and hands ngx_write_fd() a garbage descriptor.

Reproduced as a worker SIGSEGV while running APISIX's t/plugin/dubbo-proxy/upstream.t TEST 1 against apisix-runtime 1.3.16 (roughly one crash per three runs), with this backtrace from the core dump:

#0  ngx_write_fd (n=72, buf=0x7fff91488d00,
                  fd=<error reading variable: Cannot access memory at address 0x96652aad58eb38d8>)
        at src/os/unix/ngx_files.h:147
#1  ngx_log_error_core (level=8, log=0x63e8d48fa1a0, err=0,
                        fmt=0x63e8c1444fc3 "reusable connection: %ui") at src/core/ngx_log.c:195
#2  ngx_reusable_connection (c=0x63e8d48a8720, reusable=0) at src/core/ngx_connection.c:1358
#3  ngx_close_connection (c=0x63e8d48a8720) at src/core/ngx_connection.c:1313
#4  ngx_http_multi_upstream_connection_close (c=0x63e8d48a8720)
        at ngx_multi_upstream_module-1.3.3/ngx_http_multi_upstream_module.c:755

Solution

Reorder to the sequence nginx itself uses in ngx_http_close_connection() — mark the connection destroyed, take the pool aside, close, then destroy the pool. ngx_close_connection() never touches c->pool, and both callers in ngx_http_multi_upstream.c (ngx_http_multi_upstream_next and ngx_http_multi_upstream_finalize_request) treat the close as their final statement, so nothing observes the connection after it returns.

Verification

The analysis above comes from the core dump of a real crash; the fix itself is code inspection against ngx_close_connection() and the two call sites. I could not build a faithful apisix-runtime locally to re-run the reproducer against the patched module (the build installs system-wide), so a runtime build would be worth doing before release.

ngx_http_multi_upstream_connection_close() destroyed c->pool and then
called ngx_close_connection(c). ngx_close_connection() still logs through
c->log, and for these upstream connections c->log lives in the pool that
was just released, so the debug-level "reusable connection: %ui" from
ngx_reusable_connection() reads a freed ngx_log_t and dereferences a
garbage file descriptor.

Reorder to match ngx_http_close_connection(): mark the connection
destroyed, take the pool aside, close, then destroy the pool. Both callers
in ngx_http_multi_upstream.c treat the close as the final statement, so
nothing observes the connection afterwards.

Reproduces as a worker SIGSEGV on APISIX's t/plugin/dubbo-proxy/upstream.t
TEST 1 with a debug-enabled build:

    #0  ngx_write_fd (fd=<error reading variable: Cannot access memory ...>)
    #1  ngx_log_error_core (fmt="reusable connection: %ui")
    #2  ngx_reusable_connection (c=..., reusable=0)
    #3  ngx_close_connection (c=...)
    #4  ngx_http_multi_upstream_connection_close (c=...) at
        ngx_http_multi_upstream_module.c:755
@nic-6443
nic-6443 requested a lite review from Copilot August 21, 2026 09:58
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your current included review allowance is based on your included PR review attempts over the past 7 days.

Next review available in: 44 minutes

Limit details: You’ve used the included review currently available. Your 60 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

You’re in a promotional period — use the checkbox below to run this review for free:

  • Run review for free

On-demand reviews are free for the next 30 days. After that, they cost $0.25 per reviewed file.

How can I continue?

Run this review now using the option above, or comment @coderabbitai review --use-credits.

You can also wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc7f8cfb-e8a2-41ba-9f42-169d9de8a78c

📥 Commits

Reviewing files that changed from the base of the PR and between 3ac93f2 and 14e864b.

📒 Files selected for processing (1)
  • ngx_http_multi_upstream_module.c

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants