Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExceptionAlgo : Fix translatePythonException() reference counting bug #1397

Merged
merged 1 commit into from
Nov 28, 2023

Conversation

johnhaddon
Copy link
Member

The PyErr_Fetch() documentation says "you own a reference to each object retrieved", which means we need to decrement the reference count before returning, as we have no interest in sharing ownership. We were doing this via the boost::python::handle<> objects in formatInternal(), but since d0731a3 we haven't been calling formatInternal() for exceptions bound via IECorePython::ExceptionClass. That meant we were leaking such Python exceptions such that they would never be destroyed.

The solution, and the moral of the story, is to always hold PyObject * via a sensible RAII class like handle or object, and to always do that as early as possible.

You might be forgiven for thinking that leaking a little exception object isn't that big a deal. But Python exceptions have a __traceback__ attribute that contains the entire stack at the point the exception was raised, and that contains all the local variables from all of those stack frames. So the leak can actually include a completely arbitrary amount of stuff.

@johnhaddon johnhaddon self-assigned this Nov 24, 2023
@johnhaddon johnhaddon marked this pull request as ready for review November 24, 2023 15:51
@danieldresser-ie
Copy link
Contributor

LGTM

The `PyErr_Fetch()` documentation says "you own a reference to each object retrieved", which means we need to decrement the reference count before returning, as we have no interest in sharing ownership. We were doing this via the `boost::python::handle<>` objects in `formatInternal()`, but since d0731a3 we haven't been calling `formatInternal()` for exceptions bound via `IECorePython::ExceptionClass`. That meant we were leaking such Python exceptions such that they would never be destroyed.

The solution, and the moral of the story, is to always hold `PyObject *` via a sensible RAII class like `handle` or `object`, and to always do that _as early as possible_.

You might be forgiven for thinking that leaking a little exception object isn't that big a deal. But Python exceptions have a `__traceback__` attribute that contains the entire stack at the point the exception was raised, and _that_ contains all the local variables from all of those stack frames. So the leak can actually include a completely arbitrary amount of stuff.
@johnhaddon johnhaddon merged commit b985d9f into ImageEngine:RB-10.5 Nov 28, 2023
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants