Skip to content

Add __context/cause/suppress_context/traceback__ to Exception #146499

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

Closed

Conversation

[ghstack-poisoned]
Copy link

pytorch-bot bot commented Feb 5, 2025

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/146499

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 5861ae7 with merge base 50c9f6d (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
Copy link
Contributor

@zou3519 zou3519 left a comment

Choose a reason for hiding this comment

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

it is not clear to me that the setattr is done correctly for exception objects that exist outside of the compiled region

[ghstack-poisoned]
@guilhermeleobas guilhermeleobas requested a review from a team as a code owner March 3, 2025 21:32
[ghstack-poisoned]
[ghstack-poisoned]

def reconstruct(self, codegen):
if type(self.__context__) is not ConstantVariable:
unimplemented("ExceptionVariable with __context__")
codegen.add_push_null(
lambda: codegen.load_import_from("builtins", self.exc_type.__name__)
)
codegen.foreach(self.args)
Copy link
Contributor

@anijain2305 anijain2305 Mar 5, 2025

Choose a reason for hiding this comment

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

What about __cause__? If you set __cause__, you need to reconstruct that as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

From the test, it seems that setting __cause__ is reflected. But, I dont understand how.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed the code to reconstruct these attributes.

Copy link
Contributor

Choose a reason for hiding this comment

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

So there was a test that was passing without reconstruction cause. Do you know why it was happening? Just confused

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. __cause__ by default is set to None. The only way cause is set to a value different than None is with when there's a raise ... from exc but dynamo only supports the raise ... from None form.

@anijain2305
Copy link
Contributor

Looks good to me. Just have a question on __cause__ mutation.

[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
Comment on lines +1640 to +1643
# See test_exceptions::test_raise_does_not_create_context_chain_cycle
# Based on https://github.com/python/cpython/blob/e635bf2e49797ecb976ce45a67fce2201a25ca68/Python/errors.c#L207-L228
# As noted on CPython, this is O(chain length) but the context chains
# are usually very small
Copy link
Contributor

Choose a reason for hiding this comment

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

Er what is going on here? Why is this needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When setting the context attribute of an exception, there's a chance this creates a reference cycle. This piece of code is to detect and remove such cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

how exactly are you removing a reference cycle?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't set the context if it creates a cycle. There are a couple of tests that checks for this behavior. The algorithm I implemented is a straight translation of what CPython do in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

interesting

Copy link
Collaborator Author

@guilhermeleobas guilhermeleobas Mar 10, 2025

Choose a reason for hiding this comment

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

I didn't quite answer how we detect cycles. But it works as follows:
(i) Set the __context__ attribute
(ii) Detect if there's a cycle by using floyd's algorithm (ref) - One pointer moves twice as fast as the second pointer. If there's a cycle, they eventually will reach the same element.
(iii) If yes, remove the context.

[ghstack-poisoned]
[ghstack-poisoned]
@pytorchmergebot
Copy link
Collaborator

Starting merge as part of PR stack under #146502

[ghstack-poisoned]
@pytorchmergebot
Copy link
Collaborator

Starting merge as part of PR stack under #146502

@github-actions github-actions bot deleted the gh/guilhermeleobas/100/head branch April 12, 2025 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants