diff --git a/src/run/runner/valgrind/helpers/mod.rs b/src/run/runner/valgrind/helpers/mod.rs index 5001151a..cced7f52 100644 --- a/src/run/runner/valgrind/helpers/mod.rs +++ b/src/run/runner/valgrind/helpers/mod.rs @@ -1,3 +1,4 @@ pub mod ignored_objects_path; pub mod perf_maps; +pub mod python; pub mod venv_compat; diff --git a/src/run/runner/valgrind/helpers/python.rs b/src/run/runner/valgrind/helpers/python.rs new file mode 100644 index 00000000..62d93fb9 --- /dev/null +++ b/src/run/runner/valgrind/helpers/python.rs @@ -0,0 +1,21 @@ +use std::process::Command; + +/// Checks if the Python interpreter supports free-threaded mode. +/// Returns true if Python is free-threaded (GIL disabled), false otherwise. +pub fn is_free_threaded_python() -> bool { + // Use sysconfig.get_config_var("Py_GIL_DISABLED") as recommended by Python docs at https://docs.python.org/3/howto/free-threading-python.html#identifying-free-threaded-python + let output = Command::new("python") + .args([ + "-c", + "import sysconfig; print(sysconfig.get_config_var('Py_GIL_DISABLED') or 0)", + ]) + .output(); + + match output { + Ok(output) if output.status.success() => { + let stdout = String::from_utf8_lossy(&output.stdout); + stdout.trim() == "1" + } + _ => false, // If Python is not available or command fails, assume not free-threaded + } +} diff --git a/src/run/runner/valgrind/measure.rs b/src/run/runner/valgrind/measure.rs index 7c21291c..42758962 100644 --- a/src/run/runner/valgrind/measure.rs +++ b/src/run/runner/valgrind/measure.rs @@ -6,6 +6,7 @@ use crate::run::runner::helpers::introspected_golang; use crate::run::runner::helpers::introspected_nodejs; use crate::run::runner::helpers::run_command_with_log_pipe::run_command_with_log_pipe; use crate::run::runner::valgrind::helpers::ignored_objects_path::get_objects_path_to_ignore; +use crate::run::runner::valgrind::helpers::python::is_free_threaded_python; use crate::run::{config::Config, instruments::mongo_tracer::MongoTracer}; use lazy_static::lazy_static; use std::env; @@ -87,9 +88,16 @@ pub async fn measure( cmd.envs(get_base_injected_env( RunnerMode::Simulation, profile_folder, - )) - .env("PYTHONMALLOC", "malloc") - .env( + )); + + // Only set PYTHONMALLOC=malloc for non-free-threaded Python builds. + // Free-threaded Python (with GIL disabled) manages memory differently and + // should not have PYTHONMALLOC overridden. + if !is_free_threaded_python() { + cmd.env("PYTHONMALLOC", "malloc"); + } + + cmd.env( "PATH", format!( "{}:{}:{}",