Skip to content

Conversation

@realFlowControl
Copy link
Member

@realFlowControl realFlowControl commented Nov 28, 2025

Description

We got some crash reports with stacks like this:

#14  0x00006101e274a1e3 execute_ex 
#15  0x00006101e26ca4f6 zend_call_function 
#16  0x00006101e26ca8ad zend_call_known_function 
#17  0x00006101e26c9647 zend_lookup_class_ex 
#18  0x00006101e26cac0e zend_fetch_class 

None of these are actually helpful, because this would just look like a crash in the engine's execute_ex function somewhere. But now we got a new crash trace adding some stack frames that look like stack corruption, but reveal something interesting nonetheless:

#0   0x00006101e26a8712 zend_mm_gc 
#1   0x00007b434a0a82e1 get_or_init<core::cell::RefCell<datadog_php_profiling::RequestLocals>, (), fn() -> core::cell::RefCell<datadog_php_profiling::RequestLocals>> (native/lazy.rs:53:15)
#2   0x00007b434a0a82e1 {closure#0} (native/mod.rs:94:25)
#3   0x00007b434a0a82e1 call_once<datadog_php_profiling::REQUEST_LOCALS::{constant#0}::{closure_env#0}, (core::option::Option<&mut core::option::Option<core::cell::RefCell<datadog_php_profiling::RequestLocals>>>)> (src/ops/function.rs:250:5)
#4   0x00007b434a0a82e1 try_with<core::cell::RefCell<datadog_php_profiling::RequestLocals>, datadog_php_profiling::{impl#2}::try_with_borrow::{closure_env#0}<datadog_php_profiling::RequestLocals, datadog_php_profiling::allocation::alloc_prof_rshutdown::{closure_env#0}, bool>, core::result::Result<bool, core::cell::BorrowError>> (src/thread/local.rs:282:37)
#5   0x00007b434a0a82e1 try_with_borrow<datadog_php_profiling::RequestLocals, datadog_php_profiling::allocation::alloc_prof_rshutdown::{closure_env#0}, bool> (profiling/src/lib.rs:498:12)
#6   0x00007b434a0a82e1 alloc_prof_rshutdown (allocation/mod.rs:152:30)
#7   0x00007b434a0a81be get_or_init<core::cell::RefCell<datadog_php_profiling::allocation::AllocationProfilingStats>, (), fn() -> core::cell::RefCell<datadog_php_profiling::allocation::AllocationProfilingStats>> (native/lazy.rs:56:40)
#8   0x00007b434a0a81be {closure#0} (native/mod.rs:94:25)
#9   0x00007b434a0a81be call_once<datadog_php_profiling::allocation::ALLOCATION_PROFILING_STATS::{constant#0}::{closure_env#0}, (core::option::Option<&mut core::option::Option<core::cell::RefCell<datadog_php_profiling::allocation::AllocationProfilingStats>>>)> (src/ops/function.rs:250:5)
#10  0x00007b434a0a81be try_with<core::cell::RefCell<datadog_php_profiling::allocation::AllocationProfilingStats>, datadog_php_profiling::{impl#2}::try_with_borrow_mut::{closure_env#0}<datadog_php_profiling::allocation::AllocationProfilingStats, datadog_php_profiling::allocation::allocation_le83::alloc_prof_realloc::{closure_env#0}, bool>, core::result::Result<bool, core::cell::BorrowMutError>> (src/thread/local.rs:282:37)
#11  0x00007b434a0a81be try_with_borrow_mut<datadog_php_profiling::allocation::AllocationProfilingStats, datadog_php_profiling::allocation::allocation_le83::alloc_prof_realloc::{closure_env#0}, bool> (profiling/src/lib.rs:507:12)
#12  0x00007b434a0a81be borrow_mut_or_false<std::thread::local::LocalKey<core::cell::RefCell<datadog_php_profiling::allocation::AllocationProfilingStats>>, datadog_php_profiling::allocation::AllocationProfilingStats, datadog_php_profiling::allocation::allocation_le83::alloc_prof_realloc::{closure_env#0}> (profiling/src/lib.rs:489:9)
#13  0x00007b434a0a81be alloc_prof_realloc (allocation/allocation_le83.rs:418:10)
#14  0x00006101e274a1e3 execute_ex 
#15  0x00006101e26ca4f6 zend_call_function 
#16  0x00006101e26ca8ad zend_call_known_function 
#17  0x00006101e26c9647 zend_lookup_class_ex 
#18  0x00006101e26cac0e zend_fetch_class 

There is just no way that alloc_prof_realloc would call into alloc_prof_rshutdown and from there, there is no way to call into zend_mm_gc...

But there are a few ideas and things to this stack anyway: Aaccording to the runtime stack trace, it is in Composer\Autoload\ClassLoader::findFileWithExtension() line 505 which could trigger a reallocation, which on the way down, could call into zend_mm_gc. So at least this makes sense, not 100% with the stack trace we see, but ...

So anyway: I was thinking: we might not need to do all of this get_or_init() dance and use a RefCell at runtime, when we can instead initialise the ALLOCATION_PROFILING_STATS in GINIT and then just "know" that this is initialised and use it.

Reviewer checklist

  • Test coverage seems ok.
  • Appropriate labels assigned.

`UnsafeCell` and document why it is safe anyway.
@github-actions github-actions bot added profiling Relates to the Continuous Profiler tracing labels Nov 28, 2025
@realFlowControl realFlowControl marked this pull request as ready for review November 28, 2025 10:54
@realFlowControl realFlowControl requested a review from a team as a code owner November 28, 2025 10:54
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.

2 participants