Skip to content

fix: don't read PHP globals when restarting an unhealthy thread - #2696

Merged
dunglas merged 1 commit into
php:mainfrom
BastienClement:fix/unhealthy-thread-restart-segfault
Oct 10, 2026
Merged

dunglas merged 1 commit into
php:mainfrom
BastienClement:fix/unhealthy-thread-restart-segfault

Conversation

@BastienClement

Copy link
Copy Markdown
Contributor

When a thread is marked unhealthy, php_thread() calls ts_free_thread() and then logs "Restarting unhealthy thread" through frankenphp_log_message(), which reads SG(server_context). The thread no longer has TSRM storage at that point, so the read faults and the whole process segfaults instead of the thread being replaced. This started in v1.12.4, when #2438 routed that log call through frankenphp_thread_index().

Both log calls on that path now pass the thread-local thread_index to go_log(), like the go_frankenphp_on_thread_shutdown() and frankenphp_new_php_thread() calls next to them.

TestUnhealthyThreadIsRestarted makes request startup fail with a query string larger than memory_limit, then checks that the next request is served and the restart is logged. Without the fix, the test crashes the process.

Fixes #2688

frankenphp_log_message() reads SG(server_context), whose TSRM storage
ts_free_thread() has already released, so restarting an unhealthy thread
segfaulted the whole process.
Copilot AI balanced review requested due to automatic review settings October 7, 2026 08:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The targeted fix addresses both unsafe log calls, with regression coverage and no unresolved findings.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes #2688 by avoiding access to freed PHP globals when logging an unhealthy thread’s restart.

Changes:

  • Passes the thread-local index directly to both restart log calls.
  • Adds a regression test checking request recovery and restart logging after startup failure.
File Description
frankenphp.c Makes restart logging safe after PHP thread teardown.
frankenphp_test.go Tests unhealthy-thread replacement and subsequent request handling.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@dunglas
dunglas merged commit 2f8d012 into php:main Oct 10, 2026
22 checks passed
@dunglas

dunglas commented Oct 10, 2026

Copy link
Copy Markdown
Member

Thanks!

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.

Segfault of the whole process when restarting an unhealthy thread: SG(server_context) is read after ts_free_thread()

3 participants