Skip to content

fix: resolve pool-shutdown hang + reload SIGSEGV (#176) via ABI v0.24.0; pack http_request_t flags#110

Merged
EdmondDantes merged 2 commits into
mainfrom
fix/pool-shutdown-teardown-hang
Jul 9, 2026
Merged

fix: resolve pool-shutdown hang + reload SIGSEGV (#176) via ABI v0.24.0; pack http_request_t flags#110
EdmondDantes merged 2 commits into
mainfrom
fix/pool-shutdown-teardown-hang

Conversation

@EdmondDantes

Copy link
Copy Markdown
Contributor

Summary

Two long-standing flaky failures in the pool-shutdown / hot-reload tests were
runtime bugs fixed upstream in php-async, not server-repo bugs — the CI
box was simply running a PHP built one day before the fixes landed. This PR
records that finding and lands one unrelated struct-packing win from the review
backlog.

1. Root-caused two "known issues" → both resolved by ABI v0.24.0

  • Pool graceful-shutdown teardown hang (core/055–057): confirmed via gdb
    on a live hang — the main thread blocks in php_module_shutdown → libuv_reactor_quiesce joining worker threads that never exit, because the
    bootloader's persistent coroutine is never cancelled on retire. Fixed by
    php-async 937bcfe (sync-worker graceful-shutdown backstop).
  • Intermittent reload SIGSEGV (#176): cross-thread run_time_cache UAF from
    a shared nested-closure dynamic_func_defs. Fixed by php-async 0cbdfe8
    (deep-copy nested closures per worker, PR #180).

Both were verified here after rebuilding + reinstalling PHP to ABI v0.24.0:
055/056/057 PASS, and a synthetic #176 stress harness ran 30/30 clean
(≈50 % SIGSEGV before). The two docs/ISSUE_* files are updated to RESOLVED
with the full investigation trail. No server code change was needed for
either — the environment just needs php ≥ v0.24.0.

2. http_request_t: pack bool flags into a bit cluster (368 → 360 B)

The 10 per-request bool flags were 1 byte each and, with the neighbouring
1-byte scalars, rounded the struct tail up to a full 8-byte line. Convert them
to bool:1 bitfields and park the cluster in the 7-byte padding hole that
already sat after trace_flags. Named bitfields keep read/write ergonomics
(and 0/1 conversion) identical, so there are no use-site edits. A request
is single-owner (handed off by ownership, never mutated concurrently), so
non-atomic bit RMW is safe.

Testing

Full server phpt suite against the rebuilt v0.24.0 stack, all green:

suite result suite result
core 57 pass (2 skip) h3 51/51
grpc 15/15 static 23/23
h1 26/26 compression 12/12
h2 29/29 sendfile 5/5
reactor_pool 9/9 tls 15/15

Plus: 055/056/057 PASS, #176 stress harness 30/30 clean.

…BI v0.24.0

Both were runtime bugs fixed upstream in php-async, not server-repo bugs:
- pool graceful-shutdown teardown hang (core/055-057): stale php v0.23.0
  binary; fixed by php-async 937bcfe (sync-worker graceful-shutdown backstop).
- intermittent reload SIGSEGV (#176): cross-thread run_time_cache UAF from
  shared nested-closure dynamic_func_defs; fixed by php-async 0cbdfe8 (PR #180).

Verified after rebuild+reinstall to v0.24.0: 055/056/057 PASS; #176 stress
harness 30/30 clean (was ~50% SIGSEGV pre-fix). No server code change.
The 10 per-request bool flags (chunked/keep_alive/complete/use_multipart/
body_streaming/body_eof/body_error/body_paused/has_trace/persistent) were
1 byte each and, with the surrounding 1-byte scalars, rounded the struct tail
up to a full 8-byte line.

Convert them to bool:1 bitfields and park the cluster in the 7-byte padding
hole that already sat after trace_flags. Field syntax is unchanged (bool:1
keeps read/write ergonomics and 0/1 conversion), so no use-site edits. A
request is single-owner (handed off by ownership, never mutated concurrently),
so non-atomic bit RMW is safe. sizeof(http_request_t): 368 -> 360.

Verified: server phpt core 57, grpc 15, h1 26, h2 29, h3 51, static 23,
compression 12, sendfile 5, tls 15, reactor_pool 9 — all pass.
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Coverage

Total lines: 81.23% → 80.84% (-0.39 pp)

File Baseline Current Δ Touched
src/core/http_connection_tls.c 73.39% 73.67% +0.28 pp
src/core/http_protocol_handlers.c 86.25% 80.00% -6.25 pp
src/core/http_protocol_strategy.h 66.67% 33.33% -33.33 pp
src/core/worker_dispatch.c 71.78% 62.37% -9.41 pp
src/core/worker_registry.c 65.12% 61.63% -3.49 pp
src/http3/http3_callbacks.c 81.30% 80.62% -0.68 pp
src/http3/http3_dispatch.c 78.41% 78.12% -0.28 pp
src/http3/http3_listener.c 76.72% 72.74% -3.98 pp
src/http3/http3_steer.c 100.00% 87.50% -12.50 pp
src/http3/http3_stream.c 96.39% 93.98% -2.41 pp

@EdmondDantes EdmondDantes merged commit c3d88a1 into main Jul 9, 2026
7 of 8 checks passed
@EdmondDantes EdmondDantes deleted the fix/pool-shutdown-teardown-hang branch July 9, 2026 10:35
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.

1 participant