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

GH-93252: Fix error handling for failed Python calls #94693

Merged
merged 4 commits into from
Jul 9, 2022

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Jul 8, 2022

Also, add an assert so that things like this fail much earlier (and more clearly) on debug builds.

@brandtbucher brandtbucher added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump needs backport to 3.11 only security fixes labels Jul 8, 2022
@brandtbucher brandtbucher self-assigned this Jul 8, 2022
@brandtbucher brandtbucher requested a review from markshannon as a code owner July 8, 2022 18:53
Python/ceval.c Outdated
Comment on lines 6435 to 6438
PyObject **base = (PyObject **)frame;
// Make sure that this is, indeed, the top frame. We can't check this in
// _PyThreadState_PopFrame, since f_code is already cleared at that point:
assert(base + frame->f_code->co_framesize == tstate->datastack_top);
Copy link
Member Author

Choose a reason for hiding this comment

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

@pablogsal, just curious: does adding this assert (and not the fix) make tons of tests crash on your build?

If so, my theory is that your compiler is optimizing out the old assert, since the failing case is always undefined behavior according to the C standard.

Copy link
Member

Choose a reason for hiding this comment

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

I will test this night or tomorrow, but I checked and I was indeed compiling in debug mode with asserts, so the old assert should have triggered. I'm curious to see what's going on so I will also investigate that, but that won't affect this issue or the PR, is just that I'm very curious to see what's going on there :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, even if asserts were turned on, the inequality comparison between the pointers would be undefined if they're part of different allocations. Which is exactly the situation it was checking for!

So if the compiler could somehow prove that the comparison it was always true when the result was defined, it could have optimized it into assert(1) or something.

Copy link
Member Author

Choose a reason for hiding this comment

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

But yeah, it doesn't affect this PR. The thing that's better about this new assert is that it's never undefined, and we don't need to overflow our stack chunk to trigger it. One failed call should do it (which is why so many tests crash if you add this without the fix).

Copy link
Member

Choose a reason for hiding this comment

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

So if the compiler could somehow prove that the comparison it was always true when the result was defined, it could have optimized it into assert(1) or something.

I don't think so because I was compiling with -O0. If the compiler was being smart there I want my money back 🤣

Copy link
Member

@pablogsal pablogsal left a comment

Choose a reason for hiding this comment

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

LGTM

Great work 👌

@@ -26,6 +26,18 @@ def fn(**kw):
self.assertIsInstance(res, dict)
self.assertEqual(list(res.items()), expected)

def test_frames_are_popped_after_failed_calls(self):
Copy link
Member

Choose a reason for hiding this comment

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

Not that it matters much, but maybe you want to add the CPython specific decorator

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about that, but I figure that this should still pass on any CPython implementation. If you somehow crash here, it's a bug, right? 😉

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we have been approaching these kind of tests in different ways so it doesn't matter :)

Python/ceval.c Outdated Show resolved Hide resolved
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @brandtbucher for commit 5b46418 🤖

If you want to schedule another build, you need to add the ":hammer: test-with-buildbots" label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jul 8, 2022
@brandtbucher
Copy link
Member Author

brandtbucher commented Jul 8, 2022

Not sure why some of the wasm32 buildbots are failing, but it looks totally unrelated to these changes:

Warnings:

../../Python/initconfig.c:2284:27: warning: format specifies type 'wint_t' (aka 'int') but the argument has type 'wint_t' (aka 'unsigned int') [-Wformat]
../../Python/initconfig.c:2284:42: warning: format specifies type 'wint_t' (aka 'int') but the argument has type 'wint_t' (aka 'unsigned int') [-Wformat]
../../Python/pytime.c:297:10: warning: implicit conversion from 'long long' to 'double' changes value from 9223372036854775807 to 9223372036854775808 [-Wimplicit-const-int-float-conversion]
../../Python/pytime.c:352:14: warning: implicit conversion from 'long long' to 'double' changes value from 9223372036854775807 to 9223372036854775808 [-Wimplicit-const-int-float-conversion]
../../Python/pytime.c:518:10: warning: implicit conversion from 'long long' to 'double' changes value from 9223372036854775807 to 9223372036854775808 [-Wimplicit-const-int-float-conversion]
../../Modules/expat/xmlparse.c:3107:9: warning: code will never be executed [-Wunreachable-code]
../../Modules/expat/xmlparse.c:4050:9: warning: code will never be executed [-Wunreachable-code]
../../Modules/expat/xmlparse.c:7681:11: warning: format specifies type 'int' but the argument has type 'ptrdiff_t' (aka 'long') [-Wformat]
../../Modules/socketmodule.c:4001:33: warning: comparison of integers of different signs: 'unsigned long' and 'long' [-Wsign-compare]
../../Modules/socketmodule.c:4054:33: warning: comparison of integers of different signs: 'unsigned long' and 'long' [-Wsign-compare]
../../Modules/socketmodule.c:4678:54: warning: comparison of integers of different signs: 'unsigned long' and 'long' [-Wsign-compare]

Error:

error: unable to open output file 'Modules/_testcapi/vectorcall.o': 'No such file or directory'

Maybe related to #93649?

@brandtbucher
Copy link
Member Author

Maybe related to #93649?

Ah, yes, it is: #94549 (comment)

@brandtbucher brandtbucher merged commit 8a285df into python:main Jul 9, 2022
@miss-islington
Copy link
Contributor

Thanks @brandtbucher for the PR 🌮🎉.. I'm working now to backport this PR to: 3.11.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jul 9, 2022
@bedevere-bot
Copy link

GH-94699 is a backport of this pull request to the 3.11 branch.

@bedevere-bot bedevere-bot removed the needs backport to 3.11 only security fixes label Jul 9, 2022
Copy link
Contributor

@kumaraditya303 kumaraditya303 left a comment

Choose a reason for hiding this comment

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

Post commit LGTM.

@tiran
Copy link
Member

tiran commented Jul 9, 2022

Not sure why some of the wasm32 buildbots are failing, but it looks totally unrelated to these changes:

FYI, I have fixed the WASM buildbot issues in #94695. Once dependency was wrong and a directory was missing for OOT builds.

tiran pushed a commit to tiran/cpython that referenced this pull request Jul 9, 2022
kumaraditya303 pushed a commit to kumaraditya303/cpython that referenced this pull request Jul 9, 2022
miss-islington pushed a commit that referenced this pull request Jul 9, 2022
@brandtbucher brandtbucher deleted the failed-call-cleanup branch July 21, 2022 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants