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

Capsule, Unencapsulate : Fix cancellation handling #5792

Merged
merged 1 commit into from
Apr 15, 2024

Conversation

johnhaddon
Copy link
Member

We weren't omitting the canceller when copying the context in the Capsule constructor. This meant the Capsule could contain a dangling pointer to a long-since destructed Canceller, which among other things could cause IECore::Cancelled to be thrown when unencapsulating or rendering the capsule. Even if the Canceller wasn't dangling, it still wasn't suitable to be stored, because the Capsule is stored in Gaffer's cache and could be used subsequently by a client for which the original canceller doesn't apply.

A similar bug existed for the Unencapsulate node, which needs to ensure the current Canceller is used when evaluating the Capsule contents. We do this in CapsuleScope by combining the current canceller with the Context stored in the Capsule, via an EditableScope.

There was one limited scenario in which the first bug could actually have worked in our favour, and which isn't matched by the fix. When rendering a freshly-minted capsule, the canceller might have still been valid, allowing cancellation of a capsule expansion. This wouldn't have applied to any of our current rendering mechanisms though; neither batch nor interative renders use cancellation, and the Viewer doesn't expand capsules. This does point out a limitation of Capsules though (and Procedurals more generally) - we need to add a mechanism to pass cancellers to the render() method.

We weren't omitting the canceller when copying the context in the Capsule constructor. This meant the Capsule could contain a dangling pointer to a long-since destructed Canceller, which among other things could cause `IECore::Cancelled` to be thrown when unencapsulating or rendering the capsule. Even if the Canceller wasn't dangling, it still wasn't suitable to be stored, because the Capsule is stored in Gaffer's cache and could be used subsequently by a client for which the original canceller doesn't apply.

A similar bug existed for the Unencapsulate node, which needs to ensure the _current_ Canceller is used when evaluating the Capsule contents. We do this in CapsuleScope by combining the current canceller with the Context stored in the Capsule, via an EditableScope.

There was one limited scenario in which the first bug could actually have worked in our favour, and which isn't matched by the fix. When rendering a freshly-minted capsule, the canceller might have still been valid, allowing cancellation of a capsule expansion. This wouldn't have applied to any of our current rendering mechanisms though; neither batch nor interative renders use cancellation, and the Viewer doesn't expand capsules. This does point out a limitation of Capsules though (and Procedurals more generally) - we need to add a mechanism to pass cancellers to the `render()` method.
@johnhaddon johnhaddon self-assigned this Apr 15, 2024
Copy link
Contributor

@danieldresser-ie danieldresser-ie left a comment

Choose a reason for hiding this comment

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

LGTM. My only comment was about a slightly weird looking test, which doesn't need to prevent merging this if we're trying to get a release out.

context["test"] = 1

capsule = GafferScene.Capsule( sphere["out"], "/", context, hash, sphere["out"].bound( "/" ) )
self.assertIsNone( capsule.context().canceller() )
Copy link
Contributor

Choose a reason for hiding this comment

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

This test looks a bit weird - it goes to the effort of computing an accurate hash, and puts a "test" entry in the context so we can distinguish it from a default context ... but then never tests any of these things?

Copy link
Member Author

Choose a reason for hiding this comment

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

it goes to the effort of computing an accurate hash

The former I just copied from another test, not so much for testing purposes, but so that the test demonstrates that the Capsule maker is responsible for making a suitable hash. I think this is OK?

and puts a "test" entry in the context so we can distinguish it from a default context

This was me completing botching things. I had intended to use test to check that the correct context got through (just not with the canceller). And of course that context should be scoped before the hash calls.

doesn't need to prevent merging this if we're trying to get a release out.

I'm signing off now, and I agree this doesn't need to block the release. But I'll make a PR first thing tomorrow to improve the test...

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for catching that...

@murraystevenson murraystevenson merged commit 1bb711a into 1.3_maintenance Apr 15, 2024
4 checks passed
@johnhaddon johnhaddon deleted the capsuleCancellerFix branch April 16, 2024 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

3 participants