Skip to content

fix(prof) follow PHP globals model #3175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

realFlowControl
Copy link
Member

@realFlowControl realFlowControl commented Apr 1, 2025

Description

Since supporting ZTS versions of PHP, we started storing our profiler state in TLS (thread local storage). The assumption was that in PHP ZTS this would store the state per thread and helped us support ZTS PHP, while in NTS it would still store state in a TLS variable, but as there is only one thread, what gives!
Now it turns out there is at least one extension out there which does the following:

  • PHP userland code calls into an \extension\namespace\do_somthing() function
  • the C-implementation of that PHP function spawns a thread (even in NTS PHP)
  • this other thread might execute a closure that was given to an init function of the extension earlier
  • this closure might now as well allocate memory on the ZendMM
  • As our profiler has installed it's own custom ZendMM, we get called to track the allocation
  • we need to forward to the original ZendMM for the actuall allocation
  • to find that, we look it up in the TLS allocation state variable
  • which is not initialised (as that thread is not a PHP thread) so we crash 💥

Even though what that extension is doing is a race condition and violates thread safety, we should still not crash. Basically what the allocation profiler did was to make a race condition that might crash super seldom into a 100% guaranteed crash 😜

PROF-11471

Reviewer checklist

  • Test coverage seems ok.
  • Appropriate labels assigned.

@realFlowControl realFlowControl changed the title follow php globals model fix(prof) follow PHP globals model Apr 1, 2025
@github-actions github-actions bot added profiling Relates to the Continuous Profiler tracing labels Apr 1, 2025
@codecov-commenter
Copy link

codecov-commenter commented Apr 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 79.28%. Comparing base (aeeec62) to head (2bdc1c9).
Report is 3 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #3175      +/-   ##
============================================
+ Coverage     76.38%   79.28%   +2.89%     
  Complexity     2948     2948              
============================================
  Files           145      118      -27     
  Lines         16076    11633    -4443     
  Branches       1107        0    -1107     
============================================
- Hits          12280     9223    -3057     
+ Misses         3221     2410     -811     
+ Partials        575        0     -575     
Flag Coverage Δ
appsec-extension ?
tracer-php 79.28% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

see 27 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update aeeec62...2bdc1c9. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pr-commenter
Copy link

pr-commenter bot commented Apr 1, 2025

Benchmarks [ profiler ]

Benchmark execution time: 2025-04-30 15:30:46

Comparing candidate commit 2bdc1c9 in PR branch florian/zts-global-state with baseline commit aeeec62 in branch master.

Found 0 performance improvements and 2 performance regressions! Performance is the same for 29 metrics, 5 unstable metrics.

scenario:walk_stack/50

  • 🟥 wall_time [+738.839ns; +752.419ns] or [+4.866%; +4.955%]

scenario:walk_stack/99

  • 🟥 wall_time [+740.223ns; +748.205ns] or [+4.877%; +4.929%]

@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch 18 times, most recently from 71e58f0 to 386c78f Compare April 2, 2025 14:26
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 386c78f to 43c1d6f Compare April 8, 2025 08:31
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 4b03225 to 779fa59 Compare April 29, 2025 10:49
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch 4 times, most recently from f0bb47f to d09de99 Compare April 30, 2025 09:20
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 2761ecd to f5f42c9 Compare April 30, 2025 09:30
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from f5f42c9 to 003c3cf Compare April 30, 2025 09:45
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 6a09629 to 5315484 Compare April 30, 2025 10:20
@realFlowControl realFlowControl self-assigned this Apr 30, 2025
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 845c6ea to 6379bcb Compare April 30, 2025 13:46
@realFlowControl realFlowControl force-pushed the florian/zts-global-state branch from 6379bcb to 37a3256 Compare April 30, 2025 14:53
Copy link
Collaborator

@morrisonlevi morrisonlevi left a comment

Choose a reason for hiding this comment

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

I think this would still give a panic at the place we want, while not having string duplication. Linters (or maybe the compiler?) don't like panic having a constant as a format string, likes string literals.

diff --git a/profiling/src/allocation/mod.rs b/profiling/src/allocation/mod.rs
index 58437ebb9..e00158324 100644
--- a/profiling/src/allocation/mod.rs
+++ b/profiling/src/allocation/mod.rs
@@ -78,36 +78,41 @@ struct ZendMMState {
     shutdown: unsafe fn(bool, bool),
 }
 
-unsafe fn alloc_prof_panic_alloc(_len: size_t) -> *mut c_void {
+#[track_caller]
+fn init_panic() -> ! {
     panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
 }
 
+unsafe fn alloc_prof_panic_alloc(_len: size_t) -> *mut c_void {
+    init_panic();
+}
+
 unsafe fn alloc_prof_panic_realloc(_prev_ptr: *mut c_void, _len: size_t) -> *mut c_void {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 unsafe fn alloc_prof_panic_free(_ptr: *mut c_void) {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 #[cfg(php_zend_mm_set_custom_handlers_ex)]
 unsafe fn alloc_prof_panic_gc() -> size_t {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 #[cfg(php_zend_mm_set_custom_handlers_ex)]
 unsafe fn alloc_prof_panic_shutdown(_full: bool, _silent: bool) {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 #[cfg(not(php_zend_mm_set_custom_handlers_ex))]
 fn prepare_zend_heap_panic(_heap: *mut zend::_zend_mm_heap) -> c_int {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 #[cfg(not(php_zend_mm_set_custom_handlers_ex))]
 fn restore_zend_heap_panic(_heap: *mut zend::_zend_mm_heap, _custom_heap: c_int) {
-    panic!("Allocation profiler was not initialised properly. Please fill an issue stating the PHP version and the backtrace from this panic.");
+    init_panic();
 }
 
 impl ZendMMState {

@realFlowControl
Copy link
Member Author

I've committed your suggestion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
profiling Relates to the Continuous Profiler tracing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants