Skip to content

Commit

Permalink
python: Fix GC isn't working correctly.
Browse files Browse the repository at this point in the history
The uftrace_python_symbol keeps code PyObject in rb tree so GC can
not run correctly in the trace process. Fixed the problem by
dropping it. and change rb compare from code PyObject to func_name

Fixed: namhyung#1886
Signed-off-by: Yi Hong <zouzou0208@gmail.com>
Signed-off-by: Honggyu Kim <honggyu.kp@gmail.com>
  • Loading branch information
yihong0618 authored and namhyung committed Feb 17, 2024
1 parent 4d614f8 commit 25b9035
Showing 1 changed file with 19 additions and 45 deletions.
64 changes: 19 additions & 45 deletions python/trace-python.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ static union uftrace_python_symtab *dbg_info;
/* symbol table entry to maintain mappings from code to addr */
struct uftrace_python_symbol {
struct rb_node node;
PyObject *code;
char *name;
uint32_t addr;
uint32_t flag;
Expand Down Expand Up @@ -653,42 +652,14 @@ static void init_uftrace(void)
/* this is called during GC traversal */
static int uftrace_py_traverse(PyObject *m, visitproc visit, void *arg)
{
struct uftrace_py_state *state;
struct rb_node *node;
struct uftrace_python_symbol *sym;

state = PyModule_GetState(m);

Py_VISIT(state->trace_func);

node = rb_first(&code_tree);
while (node) {
sym = rb_entry(node, struct uftrace_python_symbol, node);
Py_VISIT(sym->code);

node = rb_next(node);
}
/* do nothing for now */
return 0;
}

/* this is called before the module is deallocated */
static int uftrace_py_clear(PyObject *m)
{
struct uftrace_py_state *state;
struct rb_node *node;
struct uftrace_python_symbol *sym;

state = PyModule_GetState(m);

Py_CLEAR(state->trace_func);

node = rb_first(&code_tree);
while (node) {
sym = rb_entry(node, struct uftrace_python_symbol, node);
Py_CLEAR(sym->code);

node = rb_next(node);
}
/* do nothing for now */
return 0;
}

Expand Down Expand Up @@ -878,6 +849,7 @@ static struct uftrace_python_symbol *convert_function_addr(PyObject *frame, PyOb
const char *file_name = NULL;
char *func_name;
bool is_main = false;
int cmp;

if (is_pyfunc) {
code = PyObject_GetAttrString(frame, "f_code");
Expand All @@ -889,30 +861,33 @@ static struct uftrace_python_symbol *convert_function_addr(PyObject *frame, PyOb
Py_INCREF(code);
}

if (is_pyfunc)
func_name = get_python_funcname(frame, code, &is_main);
else
func_name = get_c_funcname(frame, code);

/* code is not used anymore */
Py_DECREF(code);

if (func_name == NULL)
return NULL;

while (*p) {
parent = *p;
iter = rb_entry(parent, struct uftrace_python_symbol, node);

/* just compare pointers of the code object */
if (iter->code == code) {
Py_DECREF(code);
/* compare func_name */
cmp = strcmp(iter->name, func_name);
if (cmp == 0) {
free(func_name);
return iter;
}

if (iter->code < code)
if (cmp < 0)
p = &parent->rb_left;
else
p = &parent->rb_right;
}

if (is_pyfunc)
func_name = get_python_funcname(frame, code, &is_main);
else
func_name = get_c_funcname(frame, code);

if (func_name == NULL)
return NULL;

if (main_dir && PyObject_HasAttrString(code, "co_filename")) {
PyObject *obj;

Expand All @@ -926,7 +901,6 @@ static struct uftrace_python_symbol *convert_function_addr(PyObject *frame, PyOb
}

new_sym = xmalloc(sizeof(*new_sym));
new_sym->code = code;
new_sym->addr = get_new_sym_addr(func_name, !is_main);
new_sym->name = func_name;
new_sym->flag = is_main ? 0 : UFT_PYSYM_F_LIBCALL;
Expand Down

0 comments on commit 25b9035

Please sign in to comment.