Skip to content

Conversation

@ashm-dev
Copy link
Contributor

@ashm-dev ashm-dev commented Dec 9, 2025

@ashm-dev ashm-dev requested a review from markshannon as a code owner December 9, 2025 20:27
@ashm-dev ashm-dev changed the title gh-142476: Store chain_depth earlier and DECREF executor gh-142476: Fix memory leak in the experimental JIT compiler when creating executors. Dec 9, 2025
@ashm-dev
Copy link
Contributor Author

ashm-dev commented Dec 9, 2025

I believe a news entry is not required for this change.

Copy link
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, great catch!

Could you please add a comment(review below) so that we know why this is needed?

@Fidget-Spinner
Copy link
Member

The failing Windows test is likely because of https://github.com/python/cpython/pull/137016/files. Could you please try pulling in the changes from there?

@ashm-dev
Copy link
Contributor Author

Yes, applying the changes from #137016 fixes the Windows crash.

@Fidget-Spinner
Copy link
Member

We need this to be merged first https://github.com/python/cpython/pull/137016/files

@sergey-miryanov
Copy link
Contributor

Also, I'm not sure I get why we DECREF executor in _Py_ExecutorDetach? It is called from executor_clear with self and it doesn't seem right to me.

Maybe @markshannon can shed a light to this, because of #118459

@Fidget-Spinner
Copy link
Member

Also, I'm not sure I get why we DECREF executor in _Py_ExecutorDetach? It is called from executor_clear with self and it doesn't seem right to me.

Maybe @markshannon can shed a light to this, because of #118459

Detach is for removing the executor from a code object. The code object owns a strong reference to the executor so we must decref it.

@sergey-miryanov
Copy link
Contributor

@Fidget-Spinner Thanks!

@ashm-dev
Copy link
Contributor Author

The crashes were caused by a double untrack exposed by the fix.

  1. The original fix correctly drops the reference.
  2. If the executor is destroyed during a GC cycle (via tp_clear), the GC has already untracked the object.
  3. uop_dealloc was blindly calling _PyObject_GC_UNTRACK again, causing assertion failures (Windows) and heap corruption (Linux/Mac).

The fix: Guard the untrack call with if (_PyObject_GC_IS_TRACKED(self)).

@Fidget-Spinner
Copy link
Member

@ashm-dev that's a great observation. We need a news entry though, a short one is fine. Since this fixes a memory leak in CPython those usually need news entries.

@ashm-dev
Copy link
Contributor Author

@Fidget-Spinner I've added the news entry.

@Fidget-Spinner
Copy link
Member

So I'm gonna leave this around for a few more days. However could you please add a code comment above the if that tp_traverse might untrack the onject once it breaks cycles, so we need to not double-untrack it please?

@ashm-dev
Copy link
Contributor Author

Got it, sounds good — I’ll do that.

_PyObject_GC_UNTRACK(self);

// Object might be already untracked if we are in a GC cycle (via tp_clear).
// Avoid double-untracking.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling uop_dealloc twice means deallocating one executor twice. It seems like we're fixing symptoms, not the root of the problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add a TODO for now so we don’t lose track of this, but I don’t have the bandwidth at the moment to dig into the root cause and fix it properly.

@picnixz picnixz changed the title gh-142476: Fix memory leak in the experimental JIT compiler when creating executors. gh-142476: fix memory leak when creating JIT executors Dec 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants