Skip to content

Commit 8afb20c

Browse files
committed
refactor(profiling): simplify SystemSettings
1 parent 4e3890b commit 8afb20c

File tree

2 files changed

+64
-117
lines changed

2 files changed

+64
-117
lines changed

profiling/src/config.rs

Lines changed: 54 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::bindings::{
88
};
99
use crate::zend::zai_str_from_zstr;
1010
use core::fmt::{Display, Formatter};
11-
use core::mem::{swap, transmute, MaybeUninit};
11+
use core::mem::transmute;
1212
use core::ptr;
1313
use core::str::FromStr;
1414
use libc::{c_char, c_int};
@@ -41,16 +41,25 @@ pub struct SystemSettings {
4141
}
4242

4343
impl SystemSettings {
44-
pub fn disable_all(&mut self) {
45-
self.profiling_enabled = false;
46-
self.profiling_experimental_features_enabled = false;
47-
self.profiling_endpoint_collection_enabled = false;
48-
self.profiling_experimental_cpu_time_enabled = false;
49-
self.profiling_allocation_enabled = false;
50-
self.profiling_timeline_enabled = false;
51-
self.profiling_exception_enabled = false;
52-
self.profiling_exception_message_enabled = false;
53-
self.profiling_io_enabled = false;
44+
/// Provides "initial" settings, which are all "off"-like values.
45+
pub const fn initial() -> SystemSettings {
46+
SystemSettings {
47+
profiling_enabled: false,
48+
profiling_experimental_features_enabled: false,
49+
profiling_endpoint_collection_enabled: false,
50+
profiling_experimental_cpu_time_enabled: false,
51+
profiling_allocation_enabled: false,
52+
profiling_allocation_sampling_distance: u32::MAX,
53+
profiling_timeline_enabled: false,
54+
profiling_exception_enabled: false,
55+
profiling_exception_message_enabled: false,
56+
profiling_wall_time_enabled: false,
57+
profiling_io_enabled: false,
58+
output_pprof: None,
59+
profiling_exception_sampling_distance: u32::MAX,
60+
profiling_log_level: LevelFilter::Off,
61+
uri: AgentEndpoint::Socket(Cow::Borrowed(AgentEndpoint::DEFAULT_UNIX_SOCKET_PATH)),
62+
}
5463
}
5564

5665
/// # Safety
@@ -83,15 +92,16 @@ impl SystemSettings {
8392
}
8493
}
8594

86-
static mut SYSTEM_SETTINGS: MaybeUninit<SystemSettings> = MaybeUninit::uninit();
95+
static mut SYSTEM_SETTINGS: SystemSettings = SystemSettings::initial();
8796

8897
impl SystemSettings {
89-
/// # Safety
90-
/// Must be called after [first_rinit] and before [shutdown].
91-
pub unsafe fn get() -> ptr::NonNull<SystemSettings> {
92-
// SAFETY: required by this function's own safety requirements.
93-
let addr = unsafe { (*ptr::addr_of_mut!(SYSTEM_SETTINGS)).assume_init_mut() };
94-
ptr::NonNull::from(addr)
98+
/// Returns the "current" system settings, which are always memory-safe
99+
/// but may point to "initial" values rather than the configured ones,
100+
/// depending on what point in the lifecycle we're at.
101+
pub const fn get() -> ptr::NonNull<SystemSettings> {
102+
let addr = ptr::addr_of_mut!(SYSTEM_SETTINGS);
103+
// SAFETY: it's derived from a static variable, it's not null.
104+
unsafe { ptr::NonNull::new_unchecked(addr) }
95105
}
96106

97107
/// # Safety
@@ -110,10 +120,6 @@ impl SystemSettings {
110120
}
111121
}
112122

113-
// Initialize the lazy lock holding the env var for new origin
114-
// detection in a safe place.
115-
_ = std::sync::LazyLock::force(&libdd_common::entity_id::DD_EXTERNAL_ENV);
116-
117123
// Work around version-specific issues.
118124
#[cfg(not(php_zend_mm_set_custom_handlers_ex))]
119125
if allocation::allocation_le83::first_rinit_should_disable_due_to_jit() {
@@ -123,54 +129,21 @@ impl SystemSettings {
123129
if allocation::allocation_ge84::first_rinit_should_disable_due_to_jit() {
124130
system_settings.profiling_allocation_enabled = false;
125131
}
126-
swap(
127-
&mut system_settings,
128-
(*ptr::addr_of_mut!(SYSTEM_SETTINGS)).assume_init_mut(),
129-
);
130-
}
131132

132-
/// # Safety
133-
/// Must be called exactly once each startup in either minit or startup,
134-
/// whether profiling is enabled or not.
135-
unsafe fn on_startup() {
136-
(*ptr::addr_of_mut!(SYSTEM_SETTINGS)).write(INITIAL_SYSTEM_SETTINGS.clone());
133+
ptr::addr_of_mut!(SYSTEM_SETTINGS).swap(&mut system_settings);
137134
}
138135

139136
/// # Safety
140137
/// Must be called exactly once per shutdown in either mshutdown or
141138
/// shutdown, before zai config is shutdown.
142139
unsafe fn on_shutdown() {
143-
let system_settings = (*ptr::addr_of_mut!(SYSTEM_SETTINGS)).assume_init_mut();
144-
*system_settings = SystemSettings {
145-
profiling_enabled: false,
146-
profiling_experimental_features_enabled: false,
147-
profiling_endpoint_collection_enabled: false,
148-
profiling_experimental_cpu_time_enabled: false,
149-
profiling_allocation_enabled: false,
150-
profiling_allocation_sampling_distance: 0,
151-
profiling_timeline_enabled: false,
152-
profiling_exception_enabled: false,
153-
profiling_exception_message_enabled: false,
154-
profiling_wall_time_enabled: false,
155-
profiling_io_enabled: false,
156-
output_pprof: None,
157-
profiling_exception_sampling_distance: 0,
158-
profiling_log_level: LevelFilter::Off,
159-
uri: Default::default(),
160-
};
140+
let system_settings = &mut *ptr::addr_of_mut!(SYSTEM_SETTINGS);
141+
*system_settings = SystemSettings::initial();
161142
}
162143

163144
unsafe fn on_fork_in_child() {
164-
let system_settings = (*ptr::addr_of_mut!(SYSTEM_SETTINGS)).assume_init_mut();
165-
system_settings.profiling_enabled = false;
166-
system_settings.profiling_experimental_features_enabled = false;
167-
system_settings.profiling_endpoint_collection_enabled = false;
168-
system_settings.profiling_experimental_cpu_time_enabled = false;
169-
system_settings.profiling_allocation_enabled = false;
170-
system_settings.profiling_timeline_enabled = false;
171-
system_settings.profiling_exception_enabled = false;
172-
system_settings.profiling_exception_message_enabled = false;
173-
system_settings.profiling_io_enabled = false;
145+
let system_settings = &mut *ptr::addr_of_mut!(SYSTEM_SETTINGS);
146+
*system_settings = SystemSettings::initial();
174147
}
175148
}
176149

@@ -448,55 +421,24 @@ impl ConfigId {
448421
}
449422
}
450423

451-
lazy_static::lazy_static! {
452-
/// In some SAPIs, full configuration is not known until the first request
453-
/// is served. This is ripe for edge cases. Consider this order of events:
454-
/// 1. Worker is created.
455-
/// 2. No requests are served.
456-
/// 3. As the worker shuts down, the timeline profiler will attempt to
457-
/// add idle time to timeline.
458-
/// What state should the configuration be in?
459-
///
460-
/// Since the real configuration was never learned, assume everything is
461-
/// disabled, which should cause fewer issues for customers than assuming
462-
/// defaults.
463-
pub static ref INITIAL_SYSTEM_SETTINGS: SystemSettings = SystemSettings {
464-
profiling_enabled: false,
465-
profiling_experimental_features_enabled: false,
466-
profiling_endpoint_collection_enabled: false,
467-
profiling_experimental_cpu_time_enabled: false,
468-
profiling_allocation_enabled: false,
469-
profiling_allocation_sampling_distance: u32::MAX,
470-
profiling_timeline_enabled: false,
471-
profiling_exception_enabled: false,
472-
profiling_exception_message_enabled: false,
473-
profiling_wall_time_enabled: false,
474-
profiling_io_enabled: false,
475-
output_pprof: None,
476-
profiling_exception_sampling_distance: u32::MAX,
477-
profiling_log_level: LevelFilter::Off,
478-
uri: Default::default(),
479-
};
480-
481-
/// Keep these in sync with the INI defaults.
482-
static ref DEFAULT_SYSTEM_SETTINGS: SystemSettings = SystemSettings {
483-
profiling_enabled: true,
484-
profiling_experimental_features_enabled: false,
485-
profiling_endpoint_collection_enabled: true,
486-
profiling_experimental_cpu_time_enabled: true,
487-
profiling_allocation_enabled: true,
488-
profiling_allocation_sampling_distance: 1024 * 4096,
489-
profiling_timeline_enabled: true,
490-
profiling_exception_enabled: true,
491-
profiling_exception_message_enabled: false,
492-
profiling_wall_time_enabled: true,
493-
profiling_io_enabled: false,
494-
output_pprof: None,
495-
profiling_exception_sampling_distance: 100,
496-
profiling_log_level: LevelFilter::Off,
497-
uri: Default::default(),
498-
};
499-
}
424+
/// Keep these in sync with the INI defaults.
425+
static DEFAULT_SYSTEM_SETTINGS: SystemSettings = SystemSettings {
426+
profiling_enabled: true,
427+
profiling_experimental_features_enabled: false,
428+
profiling_endpoint_collection_enabled: true,
429+
profiling_experimental_cpu_time_enabled: true,
430+
profiling_allocation_enabled: true,
431+
profiling_allocation_sampling_distance: 1024 * 4096,
432+
profiling_timeline_enabled: true,
433+
profiling_exception_enabled: true,
434+
profiling_exception_message_enabled: false,
435+
profiling_wall_time_enabled: true,
436+
profiling_io_enabled: false,
437+
output_pprof: None,
438+
profiling_exception_sampling_distance: 100,
439+
profiling_log_level: LevelFilter::Off,
440+
uri: AgentEndpoint::Socket(Cow::Borrowed(AgentEndpoint::DEFAULT_UNIX_SOCKET_PATH)),
441+
};
500442

501443
/// # Safety
502444
/// This function must only be called after config has been initialized in
@@ -1244,7 +1186,8 @@ pub(crate) fn minit(module_number: libc::c_int) {
12441186
);
12451187
assert!(tmp); // It's literally return true in the source.
12461188

1247-
SystemSettings::on_startup();
1189+
let system_settings = &mut *ptr::addr_of_mut!(SYSTEM_SETTINGS);
1190+
*system_settings = SystemSettings::initial();
12481191
}
12491192
}
12501193

@@ -1268,6 +1211,7 @@ pub(crate) unsafe fn on_fork_in_child() {
12681211
#[cfg(test)]
12691212
mod tests {
12701213
use super::*;
1214+
use core::mem::MaybeUninit;
12711215
use libc::memcmp;
12721216

12731217
#[test]

profiling/src/lib.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mod exception;
2222
mod timeline;
2323
mod vec_ext;
2424

25-
use crate::config::{SystemSettings, INITIAL_SYSTEM_SETTINGS};
25+
use crate::config::SystemSettings;
2626
use crate::zend::datadog_sapi_globals_request_info;
2727
use bindings::{
2828
self as zend, ddog_php_prof_php_version, ddog_php_prof_php_version_id, ZendExtension,
@@ -323,6 +323,9 @@ extern "C" fn minit(_type: c_int, module_number: c_int) -> ZendResult {
323323
let _connector = libdd_common::connector::Connector::default();
324324
}
325325

326+
// Initialize the lazy lock holding the env var for new origin detection.
327+
_ = std::sync::LazyLock::force(&libdd_common::entity_id::DD_EXTERNAL_ENV);
328+
326329
// Use a hybrid extension hack to load as a module but have the
327330
// zend_extension hooks available:
328331
// https://www.phpinternalsbook.com/php7/extensions_design/zend_extensions.html#hybrid-extensions
@@ -423,7 +426,7 @@ pub struct RequestLocals {
423426
/// conditions such as in mshutdown when there were no requests served,
424427
/// then the settings are still memory safe, but they may not have the
425428
/// real configuration. Instead, they have a best-effort values such as
426-
/// INITIAL_SYSTEM_SETTINGS, or possibly the values which were available
429+
/// the initial settings, or possibly the values which were available
427430
/// in MINIT.
428431
pub system_settings: ptr::NonNull<SystemSettings>,
429432

@@ -434,8 +437,9 @@ pub struct RequestLocals {
434437
impl RequestLocals {
435438
#[track_caller]
436439
pub fn system_settings(&self) -> &SystemSettings {
437-
// SAFETY: it should always be valid, either set to the
438-
// INITIAL_SYSTEM_SETTINGS or to the SYSTEM_SETTINGS.
440+
// SAFETY: it should always be valid, just maybe "stale", such as
441+
// having only the initial values, or only the ones available in minit,
442+
// rather than the fully configured values.
439443
unsafe { self.system_settings.as_ref() }
440444
}
441445
}
@@ -449,7 +453,7 @@ impl Default for RequestLocals {
449453
git_commit_sha: None,
450454
git_repository_url: None,
451455
tags: vec![],
452-
system_settings: ptr::NonNull::from(INITIAL_SYSTEM_SETTINGS.deref()),
456+
system_settings: SystemSettings::get(),
453457
interrupt_count: AtomicU32::new(0),
454458
vm_interrupt_addr: ptr::null_mut(),
455459
}
@@ -572,8 +576,7 @@ extern "C" fn rinit(_type: c_int, _module_number: c_int) -> ZendResult {
572576

573577
unsafe { bindings::zai_config_rinit() };
574578

575-
// SAFETY: We are after first rinit and before config mshutdown.
576-
let mut system_settings = unsafe { SystemSettings::get() };
579+
let mut system_settings = SystemSettings::get();
577580

578581
// initialize the thread local storage and cache some items
579582
let result = REQUEST_LOCALS.try_with_borrow_mut(|locals| {

0 commit comments

Comments
 (0)