Skip to content

fix(http): release the cached addresses of keep-alive sessions in process mode - #6285

Closed
EJ-Research wants to merge 1 commit into
swoole:masterfrom
EJ-Research:fix-http-process-ip-cache
Closed

EJ-Research wants to merge 1 commit into
swoole:masterfrom
EJ-Research:fix-http-process-ip-cache

Conversation

@EJ-Research

Copy link
Copy Markdown
Contributor

Fixes #6283

Bug

  • A keep-alive HTTP request from a non-loopback address caches its server_addr and remote_addr strings per session in the worker
  • [6.2]add server_addr #5994 in v6.2.0 extended this cache from SWOOLE_BASE to SWOOLE_PROCESS with dispatch_mode 2
  • php_swoole_http_server_onClose() erases the entries but on_before_start() still installs it in SWOOLE_BASE mode only
  • So in SWOOLE_PROCESS mode every such connection keeps two strings in the worker heap until the worker exits
  • A user onClose callback does not help since php_swoole_server_onClose() does not touch the cache

One worker and the growth of memory_get_usage() in the worker per connection

Case Before After
HTTP/1.1 keep-alive closed by the client 80.00 bytes 0
The same with empty onConnect and onClose callbacks 80.00 bytes 0
The same with send_yield or enable_coroutine off 80.00 bytes 0
Closed by the server after a keep-alive request 80.00 bytes 0
Closed by another worker after a keep-alive request 80.00 bytes 0
WebSocket closed by the client 80.00 bytes 0
HTTP/2 closed by the client 80.00 bytes 0
Connection: close or 127.0.0.1 or SWOOLE_BASE or any other dispatch_mode 0 0
  • The 6.2 branch at 522f1cc gives 80.00 bytes before and 0 after
  • The 6.1 branch at bb7880e gives 0 since it caches in SWOOLE_BASE mode only

Fix

  • swoole_http_server_is_ip_cache_enabled() now decides both whether the addresses are cached and whether php_swoole_http_server_onClose() is installed
  • With dispatch_mode 2 the close event of a session goes to the worker that holds its entries
  • send_yield is on by default and then php_swoole_server_onClose() is already installed so the change only swaps it for the HTTP variant that erases two entries and calls it
  • With send_yield or enable_coroutine off nothing was installed before and a close now takes the same path as with an empty user onClose callback

Tests

  • The new tests/swoole_http_server/server_addr_released_on_close.phpt fails on master with 40256 bytes for 500 connections and passes with the fix
  • tests/swoole_http_server and swoole_websocket_server and swoole_http2_server and swoole_server give the same results before and after except the new test
  • A few swoole_server timing tests changed between runs and failed at the same rate on both builds when they were repeated alone
  • Every dispatch_mode with and without callbacks and with send_yield or enable_coroutine off gave the same replies and closed connections and onClose calls and log lines before and after
  • valgrind with USE_ZEND_ALLOC=0 found no error in the master and the manager and the worker by default and with send_yield or enable_coroutine off
  • 20000 client-closed connections with 4 CPUs took 2.30 s before and 2.22 s after as the median of six runs in ABBA order
  • The patch applies to the 6.2 branch and gives 0 there

@NathanFreeman

NathanFreeman commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

If possible, please merge this PR into the 6.2 branch. Thank You.

@NathanFreeman

Copy link
Copy Markdown
Member

Thank you for your contribution. However, this fix needs to be merged into the 6.2 branch. I have created a new PR for this: #6292

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.

In SWOOLE_PROCESS mode every connection closed by the client keeps 80 bytes of worker heap

2 participants