Reloading USD Stages Causes UseAfterFree Error

   78   0   1
User Avatar
Member
3 posts
Joined: May 2019
Offline
## Hello USD Users,

I'm currently working on an open-source USD Resolver and need some help refreshing a LOPs node stage. My primary goal is to reload all assets, which would be useful for clearing the resolver. In the future, I aim to implement functionality to reload specific assets selectively.

### The Problem

I assumed that running `.Reload()` on the stage provided by a node would cause the resolver to trigger `__RefreshContext()`, thereby refreshing the context and informing the stage that all resolves done with a given resolver are invalid. However, to my surprise, I encountered a *UseAfterFree* error.

I wasn’t able to dig too deeply into this with GDB, but I found that a series of locks were accessed by Houdini and one PXR lock (`pxrInternal_v0_24__pxrReserved__::XUSD_Data::afterLock`). This all occurred in a single thread within a combination of `libHoudiniUSD` and `libHoudiniAPPS3`. My assumption is that Houdini keeps the stage or layer pointer cached for later use, and when the resolver gets destructed, this leaves behind a dangling pointer.

### Issues Encountered
1. **Reloading USD Stage from Python LOP**: Attempting `.Reload()` on the stage not only fails but also causes a *use-after-free* error, resulting in segmentation faults.
2. **Resolver Context Notifications**:
- When I notify the stage that a resolver context has changed, all matching contexts are deleted. However, I don’t observe new resolutions.
- Based on the documentation, I assumed Houdini would reload everything since the notification invalidates the current resolver context, ensuring the user is shown up-to-date information.
3. **Re-resolution on Node Connection**:
- When connecting a new node, the entire stage is re-resolved, but this only occurs if something new is resolved.
- Is this behavior expected? I assumed the re-resolution would happen immediately after the stage is invalidated.

### Example Script
Here's a minimal script to reproduce the issue:

1. Go to LOPs.
2. Load something.
3. Run this in a Python LOP:
```python
node = hou.pwd()
stage = node.editableStage()
stage.Reload()
```

### Questions
1. Why does `.Reload()` fail and cause a segfault? Is it related to the stage being backed by an anonymous `SdfLayer`?
2. What is the expected behavior of the resolver context notification? Shouldn’t it trigger a reload automatically?
3. Is it normal for the stage to be re-resolved only when a new asset is resolved, rather than immediately after invalidation?

Any insights or suggestions to address these issues would be greatly appreciated!

Thanks in advance for your help!
Lyon Rosenblatt
  • Quick Links