@@ -34,14 +34,13 @@ use core::ptr;
3434use lazy_static:: lazy_static;
3535use libdd_common:: { cstr, tag, tag:: Tag } ;
3636use log:: { debug, error, info, trace, warn} ;
37- use once_cell:: sync:: { Lazy , OnceCell } ;
3837use profiling:: { LocalRootSpanResourceMessage , Profiler , VmInterrupt } ;
3938use sapi:: Sapi ;
4039use std:: borrow:: Cow ;
4140use std:: cell:: { BorrowError , BorrowMutError , RefCell } ;
4241use std:: ops:: { Deref , DerefMut } ;
4342use std:: sync:: atomic:: { AtomicBool , AtomicU32 , Ordering } ;
44- use std:: sync:: { Arc , Once } ;
43+ use std:: sync:: { Arc , Once , OnceLock } ;
4544use std:: thread:: { AccessError , LocalKey } ;
4645use std:: time:: { Duration , Instant } ;
4746use uuid:: Uuid ;
@@ -146,7 +145,7 @@ lazy_static! {
146145/// Additionally, the tracer is going to ask for this in its ACTIVATE handler,
147146/// so whatever it is replaced with needs to also follow the
148147/// initialize-on-first-use pattern.
149- static RUNTIME_ID : OnceCell < Uuid > = OnceCell :: new ( ) ;
148+ static RUNTIME_ID : OnceLock < Uuid > = OnceLock :: new ( ) ;
150149// If ddtrace is loaded, we fetch the uuid from there instead
151150extern "C" {
152151 pub static ddtrace_runtime_id: * const Uuid ;
@@ -159,55 +158,62 @@ extern "C" {
159158#[ cfg( php_zts) ]
160159static mut GLOBALS_ID_PTR : i32 = 0 ;
161160
162- /// The function `get_module` is what makes this a PHP module. Please do not
163- /// call this directly; only let it be called by the engine. Generally it is
164- /// only called once, but if someone accidentally loads the module twice then
165- /// it might get called more than once, though it will warn and not use the
166- /// consecutive return value.
161+ /// Module dependencies for the profiler extension.
162+ static MODULE_DEPS : [ zend:: ModuleDep ; 8 ] = [
163+ zend:: ModuleDep :: required ( cstr ! ( "standard" ) ) ,
164+ zend:: ModuleDep :: required ( cstr ! ( "json" ) ) ,
165+ zend:: ModuleDep :: optional ( cstr ! ( "ddtrace" ) ) ,
166+ // Optionally, be dependent on these event extensions so that the functions they provide
167+ // are registered in the function table and we can hook into them.
168+ zend:: ModuleDep :: optional ( cstr ! ( "ev" ) ) ,
169+ zend:: ModuleDep :: optional ( cstr ! ( "event" ) ) ,
170+ zend:: ModuleDep :: optional ( cstr ! ( "libevent" ) ) ,
171+ zend:: ModuleDep :: optional ( cstr ! ( "uv" ) ) ,
172+ zend:: ModuleDep :: end ( ) ,
173+ ] ;
174+
175+ /// The module entry for the profiler extension. Fields that aren't
176+ /// const-compatible are set in get_module().
177+ static mut MODULE : zend:: ModuleEntry = zend:: ModuleEntry {
178+ deps : MODULE_DEPS . as_ptr ( ) ,
179+ name : PROFILER_NAME . as_ptr ( ) ,
180+ functions : ptr:: null ( ) , // Will be set in get_module()
181+ module_startup_func : Some ( minit) ,
182+ module_shutdown_func : Some ( mshutdown) ,
183+ request_startup_func : Some ( rinit) ,
184+ request_shutdown_func : Some ( rshutdown) ,
185+ info_func : Some ( minfo) ,
186+ version : PROFILER_VERSION . as_ptr ( ) ,
187+ globals_size : 1 ,
188+ #[ cfg( php_zts) ]
189+ globals_id_ptr : ptr:: addr_of_mut!( GLOBALS_ID_PTR ) ,
190+ #[ cfg( not( php_zts) ) ]
191+ globals_ptr : ptr:: null_mut ( ) ,
192+ globals_ctor : Some ( ginit) ,
193+ globals_dtor : Some ( gshutdown) ,
194+ post_deactivate_func : Some ( prshutdown) ,
195+ build_id : ptr:: null ( ) , // Will be set in get_module()
196+ ..zend:: ModuleEntry :: new ( )
197+ } ;
198+
199+ /// The function `get_module` is what makes this a PHP module.
200+ ///
201+ /// # Safety
202+ ///
203+ /// Do not call this function manually; it will be called by the engine.
204+ /// Generally it is only called once, but if someone accidentally loads the
205+ /// module twice then it might get called more than once, though it will warn
206+ /// and not use the consecutive return value.
167207#[ no_mangle]
168- pub extern "C" fn get_module ( ) -> & ' static mut zend:: ModuleEntry {
169- static DEPS : [ zend:: ModuleDep ; 8 ] = [
170- zend:: ModuleDep :: required ( cstr ! ( "standard" ) ) ,
171- zend:: ModuleDep :: required ( cstr ! ( "json" ) ) ,
172- zend:: ModuleDep :: optional ( cstr ! ( "ddtrace" ) ) ,
173- // Optionally, be dependent on these event extensions so that the functions they provide
174- // are registered in the function table and we can hook into them.
175- zend:: ModuleDep :: optional ( cstr ! ( "ev" ) ) ,
176- zend:: ModuleDep :: optional ( cstr ! ( "event" ) ) ,
177- zend:: ModuleDep :: optional ( cstr ! ( "libevent" ) ) ,
178- zend:: ModuleDep :: optional ( cstr ! ( "uv" ) ) ,
179- zend:: ModuleDep :: end ( ) ,
180- ] ;
181-
182- // In PHP modules written in C, this just returns the address of a global,
183- // mutable variable. In Rust, you cannot initialize such a complicated
184- // global variable because of initialization order issues that have been
185- // found through decades of C++ experience.
186- // There are a variety of ways to deal with this; this is just one way.
187- static mut MODULE : Lazy < zend:: ModuleEntry > = Lazy :: new ( || zend:: ModuleEntry {
188- name : PROFILER_NAME . as_ptr ( ) ,
189- // SAFETY: php_ffi.c defines this correctly
190- functions : unsafe { bindings:: ddog_php_prof_functions } ,
191- module_startup_func : Some ( minit) ,
192- module_shutdown_func : Some ( mshutdown) ,
193- request_startup_func : Some ( rinit) ,
194- request_shutdown_func : Some ( rshutdown) ,
195- info_func : Some ( minfo) ,
196- version : PROFILER_VERSION . as_ptr ( ) ,
197- post_deactivate_func : Some ( prshutdown) ,
198- deps : DEPS . as_ptr ( ) ,
199- globals_ctor : Some ( ginit) ,
200- globals_dtor : Some ( gshutdown) ,
201- globals_size : 1 ,
202- #[ cfg( php_zts) ]
203- globals_id_ptr : ptr:: addr_of_mut!( GLOBALS_ID_PTR ) ,
204- #[ cfg( not( php_zts) ) ]
205- globals_ptr : ptr:: null_mut ( ) ,
206- ..Default :: default ( )
207- } ) ;
208+ pub unsafe extern "C" fn get_module ( ) -> * mut zend:: ModuleEntry {
209+ let module = ptr:: addr_of_mut!( MODULE ) ;
208210
209- // SAFETY: well, it's at least as safe as what every single C extension does.
210- unsafe { & mut * ptr:: addr_of_mut!( MODULE ) }
211+ // Set fields that aren't const-compatible.
212+ unsafe {
213+ ptr:: addr_of_mut!( ( * module) . functions) . write ( bindings:: ddog_php_prof_functions) ;
214+ ptr:: addr_of_mut!( ( * module) . build_id) . write ( bindings:: datadog_module_build_id ( ) ) ;
215+ }
216+ module
211217}
212218
213219unsafe extern "C" fn ginit ( _globals_ptr : * mut c_void ) {
0 commit comments