-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Python bindings: segfault enumerating result of Traverse() from Usd.Stage #2160
Comments
Hi @jakedouglas , given that you have assigned the stage to a python local, it seems unlikely that python would garbage collect the stage. Does this happen with a "known good" usdz asset, like any of those from the Apple QuickLook gallery? If it turns out to be specific to a particular usdz asset, if it is not too big, could you share it for further debugging? If it seems like a more systemic issue, it's something I do not know that we can reproduce, given that we test the pypi and other builds prior to publishing. In that case, are there any scenarios in which you can successfully open and traverse a UsdStage? Build (a simple) one programatically? |
Two examples were provided for comparison:
Let me know if I can further clarify. |
Ah, sorry, @jakedouglas - somehow I missed the second example! So
is not expected to work, because Bottom line, to do anything with a Stage other than use its I am, however, concerned that you got a segfault, rather than a python exception telling you about an attempt to dereference an expired UsdPrim. That's the behavior we observe, and expect. |
In C++ the result of |
Thank you for explaining. I think it is probably unintuitive for Python users to have a I do get the exception under Python 3.10, but segfault under Python 3.8 and 3.9. What additional information can I provide to be helpful? |
Notably this segfault also occurs using the universal2 wheel produced from the
|
We're taking a look to see if we can repro and diagnose, @jakedouglas ... in our internal builds, your python code produces a python exception as we expect(!) |
Filed as internal issue #USD-7872 |
I did some tests using the manylinux2014 Docker image using usd-core 22.11 and got exceptions on Python 3.6 and 3.7 but segfaults on 3.8, 3.9, and 3.10. The exceptions looked like:
I'm wondering if there was some C API change in 3.8 that's affecting the way we (or boost::python) is translating exceptions now. |
Oh nevermind, I've found the issue and am testing a fix that will avoid the segfault and cause an exception to be thrown consistently instead. This appears to be a long-standing issue and will likely not make the cut for the 23.02 release but will land in the dev branch shortly after. |
These functions are all intended for use in C++ code called from Python bindings. In these cases, the GIL has already been acquired, so the TfPyLocks in these functions were redundant. Fixes #2160 (Internal change: 2262124)
__iter__ was missing a call to throw_error_already_set after using the Python C API to set an error indicator, resulting in a SystemError exception on Python 3.6 and 3.7 and segfaults on 3.8+. This fix replaces direct calls to the Python API with Tf utility functions which ensure that throw_error_already_set will be called in error cases. Fixes #2160 (Internal change: 2262128)
Description of Issue
Enumerating a
Usd.PrimRange
obtained from callingTraverse()
on a loaded stage segfaults when a reference to the stage is not explicitly maintained. It seems as though it may be getting garbage collected prematurely.Steps to Reproduce
Works fine:
Segfaults:
Package Versions
Python 3.9
Seen on multiple systems:
Result:
cc @gavinmh
The text was updated successfully, but these errors were encountered: