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-91079: Decouple C stack overflow checks from Python recursion checks. #96510

Merged
merged 10 commits into from Oct 5, 2022

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Sep 2, 2022

@markshannon markshannon marked this pull request as ready for review Sep 5, 2022
@markshannon markshannon added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 5, 2022
@bedevere-bot
Copy link

bedevere-bot commented Sep 5, 2022

🤖 New build scheduled with the buildbot fleet by @markshannon for commit e8a1bed 🤖

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

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 5, 2022
@markshannon markshannon added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 5, 2022
@bedevere-bot
Copy link

bedevere-bot commented Sep 5, 2022

🤖 New build scheduled with the buildbot fleet by @markshannon for commit 7e21a74 🤖

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

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 5, 2022
@markshannon markshannon added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 6, 2022
@bedevere-bot
Copy link

bedevere-bot commented Sep 6, 2022

🤖 New build scheduled with the buildbot fleet by @markshannon for commit 65cca7d 🤖

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

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 6, 2022
@markshannon markshannon added the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 13, 2022
@bedevere-bot
Copy link

bedevere-bot commented Sep 13, 2022

🤖 New build scheduled with the buildbot fleet by @markshannon for commit d75797c 🤖

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

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Sep 13, 2022
@markshannon markshannon requested a review from gpshead Sep 15, 2022
@gpshead gpshead added the sprint label Oct 3, 2022
@gpshead gpshead self-assigned this Oct 4, 2022
# 1,000 on most systems
limit = sys.getrecursionlimit()
code = "lambda: " + "+".join(f"_number_{i}" for i in range(limit))
# Need more than 256 variables to use EXTENDED_ARGS
Copy link
Member

@gpshead gpshead Oct 4, 2022

Choose a reason for hiding this comment

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

I assume EXTENDED_ARGS has stack implications? explaining the "why" of this here would be useful.

# and is equal to recursion_limit when _gen_throw() calls
# PyErr_NormalizeException().
recurse(setrecursionlimit(depth + 2) - depth)
recurse(5000)
Copy link
Member

@gpshead gpshead Oct 4, 2022

Choose a reason for hiding this comment

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

There's a constant of 5000 used in all sorts of tests for the same purpose of being "too high" for recursion with this PR. I suggest making this a named test.support constant and referring to it instead of mystery constants spread throughout the test suite.

Copy link
Member

@gpshead gpshead Oct 4, 2022

Choose a reason for hiding this comment

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

(and where other constants are derived from that to be higher or lower scale, use math from the main value?)

/* WASI has limited call stack. Python's recursion limit depends on code
layout, optimization, and WASI runtime. Wasmtime can handle about 700
recursions, sometimes less. 500 is a more conservative limit. */
#ifndef Py_DEFAULT_RECURSION_LIMIT
Copy link
Member

@gpshead gpshead Oct 4, 2022

Choose a reason for hiding this comment

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

ifndef C_RECURSION_LIMIT

# define Py_DEFAULT_RECURSION_LIMIT 1000
# endif
#endif
#define Py_DEFAULT_RECURSION_LIMIT 1000
Copy link
Member

@gpshead gpshead Oct 4, 2022

Choose a reason for hiding this comment

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

keep the ifndef around this, those exist to allow someone setting their own via CFLAGS.

@markshannon markshannon requested a review from rhettinger as a code owner Oct 4, 2022
@markshannon markshannon requested a review from tiran as a code owner Oct 4, 2022
gpshead
gpshead approved these changes Oct 4, 2022
Copy link
Member

@gpshead gpshead left a comment

this tied in nicely with the 3.11 talk :)

@markshannon markshannon merged commit 7644935 into python:main Oct 5, 2022
14 checks passed
@tacaswell
Copy link
Contributor

tacaswell commented Oct 7, 2022

This broke compilation of https://github.com/python-greenlet/greenlet/

✔ 20:08:04 $ gcc -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/home/tcaswell/.virtualenvs/bleeding/include -I/home/tcaswell/.pybuild/bleeding/include/python3.12 -c src/greenlet/greenlet.cpp -o build/temp.linux-x86_64-3.12/src/greenlet/greenlet.o
In file included from src/greenlet/greenlet_internal.hpp:19,
                 from src/greenlet/greenlet.cpp:17:
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::operator<<(const PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:826:37: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
  826 |     this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
      |                                     ^~~~~~~~~~~~~~~
      |                                     py_recursion_limit
src/greenlet/greenlet_greenlet.hpp:826:63: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
  826 |     this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
      |                                                               ^~~~~~~~~~~~~~~~~~~
      |                                                               c_recursion_remaining
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::operator>>(PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:859:13: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
  859 |     tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth;
      |             ^~~~~~~~~~~~~~~~~~~
      |             c_recursion_remaining
src/greenlet/greenlet_greenlet.hpp:859:43: error: ‘PyThreadState’ {aka ‘struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
  859 |     tstate->recursion_remaining = tstate->recursion_limit - this->recursion_depth;
      |                                           ^~~~~~~~~~~~~~~
      |                                           py_recursion_limit
src/greenlet/greenlet_greenlet.hpp: In member function ‘void greenlet::PythonState::set_initial_state(const PyThreadState*)’:
src/greenlet/greenlet_greenlet.hpp:886:37: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_limit’; did you mean ‘py_recursion_limit’?
  886 |     this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
      |                                     ^~~~~~~~~~~~~~~
      |                                     py_recursion_limit
src/greenlet/greenlet_greenlet.hpp:886:63: error: ‘const PyThreadState’ {aka ‘const struct _ts’} has no member named ‘recursion_remaining’; did you mean ‘c_recursion_remaining’?
  886 |     this->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining;
      |                                                               ^~~~~~~~~~~~~~~~~~~
      |                                                               c_recursion_remaining

Doing the renames as suggested by the compiler fixes it (although from reading the PR here, maybe py_recursion_remaining should be used instead of c_recursion_remaining).

Is this an unintended side effect of this change and or does greenlets need to adapt?

@gpshead
Copy link
Member

gpshead commented Oct 7, 2022

Not being familiar with greenlet much I suspect it wants py_recursion_remaining. This is a rather internal structure that changes between releases. https://docs.python.org/3.11/whatsnew/3.11.html has a change around these that you've adapted to in https://github.com/python-greenlet/greenlet/blob/master/src/greenlet/greenlet_greenlet.hpp#L825 so this is probably just another one that we need to document in 3.12's "What's New".

@gpshead
Copy link
Member

gpshead commented Oct 7, 2022

BTW @tacaswell major kudos to you for testing against CPython main =)

@tacaswell
Copy link
Contributor

tacaswell commented Oct 7, 2022

Thanks, I'll get a PR to greenlet done in the next few days (I am also barely familiar with greenlet but it is a dependency of a dependency of something I care about).

I have built a whole rube-goldberg machine to test CPython main (https://github.com/tacaswell/build_the_world).

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.

None yet

4 participants