Skip to content

Commit 34842a0

Browse files
committed
codetracer-python-recorder/src/runtime_tracer.rs: fix deadlock due to sys import
codetracer-python-recorder/tests/test_fail_fast_on_py_start.py: remove stupid test Signed-off-by: Tzanko Matev <[email protected]>
1 parent dad0627 commit 34842a0

File tree

2 files changed

+39
-57
lines changed

2 files changed

+39
-57
lines changed

codetracer-python-recorder/src/runtime_tracer.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,38 @@ impl Tracer for RuntimeTracer {
269269
let mut args: Vec<runtime_tracing::FullValueRecord> = Vec::new();
270270
let frame_and_args = (|| -> PyResult<()> {
271271
// Current Python frame where the function just started executing
272-
let sys = py.import("sys")?;
273-
let frame = sys.getattr("_getframe")?.call1((0,))?;
274-
let locals = frame.getattr("f_locals")?;
272+
273+
// Acquire current frame without importing sys
274+
let mut frame_ptr = unsafe { ffi::PyEval_GetFrame() };
275+
if frame_ptr.is_null() {
276+
return Err(pyo3::exceptions::PyRuntimeError::new_err(
277+
"on_py_start: null frame",
278+
));
279+
}
280+
unsafe {
281+
ffi::Py_XINCREF(frame_ptr.cast());
282+
}
283+
284+
// Synchronize fast locals into f_locals
285+
unsafe {
286+
if ffi::PyFrame_FastToLocalsWithError(frame_ptr) < 0 {
287+
ffi::Py_DECREF(frame_ptr.cast());
288+
let err = PyErr::fetch(py);
289+
return Err(err);
290+
}
291+
}
292+
293+
// Obtain concrete locals dict for lookup
294+
let locals_raw = unsafe { PyFrame_GetLocals(frame_ptr) };
295+
if locals_raw.is_null() {
296+
unsafe {
297+
ffi::Py_DECREF(frame_ptr.cast());
298+
}
299+
return Err(pyo3::exceptions::PyRuntimeError::new_err(
300+
"on_py_start: PyFrame_GetLocals returned null",
301+
));
302+
}
303+
let locals = unsafe { Bound::<PyAny>::from_owned_ptr(py, locals_raw) };
275304

276305
// Argument names come from co_varnames in the order defined by CPython:
277306
// [positional (pos-only + pos-or-kw)] [+ varargs] [+ kw-only] [+ kwargs]
@@ -280,9 +309,10 @@ impl Tracer for RuntimeTracer {
280309
// for the positional slice; `co_posonlyargcount` is only needed if we want to
281310
// distinguish the two groups, which we do not here.
282311
let argcount = code.arg_count(py)? as usize; // total positional (pos-only + pos-or-kw)
312+
283313
let _posonly: usize = code.as_bound(py).getattr("co_posonlyargcount")?.extract()?;
284-
let kwonly: usize = code.as_bound(py).getattr("co_kwonlyargcount")?.extract()?;
285314

315+
let kwonly: usize = code.as_bound(py).getattr("co_kwonlyargcount")?.extract()?;
286316
let flags = code.flags(py)?;
287317
const CO_VARARGS: u32 = 0x04;
288318
const CO_VARKEYWORDS: u32 = 0x08;
@@ -300,7 +330,7 @@ impl Tracer for RuntimeTracer {
300330
let vrec = self.encode_value(py, &val);
301331
args.push(TraceWriter::arg(&mut self.writer, name, vrec));
302332
}
303-
Err(_) => {}
333+
Err(e) => {panic!("Error {:?}",e)}
304334
}
305335
idx += 1;
306336
}
@@ -323,7 +353,7 @@ impl Tracer for RuntimeTracer {
323353
let vrec = self.encode_value(py, &val);
324354
args.push(TraceWriter::arg(&mut self.writer, name, vrec));
325355
}
326-
Err(_) => {}
356+
Err(e) => {panic!("Error {:?}", e)}
327357
}
328358
}
329359
idx = idx.saturating_add(kwonly_take);
@@ -336,6 +366,7 @@ impl Tracer for RuntimeTracer {
336366
args.push(TraceWriter::arg(&mut self.writer, name, vrec));
337367
}
338368
}
369+
unsafe { ffi::Py_DECREF(frame_ptr.cast()); }
339370
Ok(())
340371
})();
341372
if let Err(e) = frame_and_args {
@@ -344,7 +375,8 @@ impl Tracer for RuntimeTracer {
344375
"on_py_start: failed to capture args: {}",
345376
e
346377
)));
347-
log::debug!("error {:?}", rete);
378+
//panic!("error {:?}", rete);
379+
log::error!("AAA error {:?}", rete);
348380
return rete;
349381
}
350382

codetracer-python-recorder/tests/test_fail_fast_on_py_start.py

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)