-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-32307: thread: fix stack size on musl platforms. #26224
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Force a default thread stack size value for all platforms instead of | ||
assuming that they all have enough for Python threads. This makes it so too | ||
many recursions are caught by the interpreter instead of stack overflowing | ||
on musl libc. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,9 @@ | |
be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */ | ||
#ifdef _POSIX_THREAD_ATTR_STACKSIZE | ||
#ifndef THREAD_STACK_SIZE | ||
#define THREAD_STACK_SIZE 0 /* use default stack size */ | ||
/* -1 means THREAD_STACK_SIZE hasn't been given a proper value yet. | ||
-DTHREAD_STACK_SIZE=0 in CFLAGS will force the platform's default instead. */ | ||
#define THREAD_STACK_SIZE -1 | ||
#endif | ||
|
||
/* The default stack size for new threads on OSX and BSD is small enough that | ||
|
@@ -39,33 +41,35 @@ | |
* The default stack sizes below are the empirically determined minimal stack | ||
* sizes where a simple recursive function doesn't cause a hard crash. | ||
*/ | ||
#if defined(__APPLE__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 | ||
#if defined(__APPLE__) && THREAD_STACK_SIZE == -1 | ||
#undef THREAD_STACK_SIZE | ||
/* Note: This matches the value of -Wl,-stack_size in configure.ac */ | ||
#define THREAD_STACK_SIZE 0x1000000 | ||
#endif | ||
#if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 | ||
#if defined(__FreeBSD__) && THREAD_STACK_SIZE == -1 | ||
#undef THREAD_STACK_SIZE | ||
#define THREAD_STACK_SIZE 0x400000 | ||
#endif | ||
#if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 | ||
#undef THREAD_STACK_SIZE | ||
#define THREAD_STACK_SIZE 0x200000 | ||
#endif | ||
/* bpo-38852: test_threading.test_recursion_limit() checks that 1000 recursive | ||
Python calls (default recursion limit) doesn't crash, but raise a regular | ||
RecursionError exception. In debug mode, Python function calls allocates | ||
more memory on the stack, so use a stack of 8 MiB. */ | ||
#if defined(__ANDROID__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 | ||
#if defined(__ANDROID__) && THREAD_STACK_SIZE == -1 | ||
# ifdef Py_DEBUG | ||
# undef THREAD_STACK_SIZE | ||
# define THREAD_STACK_SIZE 0x800000 | ||
# endif | ||
#endif | ||
#if defined(__VXWORKS__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0 | ||
#if defined(__VXWORKS__) && THREAD_STACK_SIZE == -1 | ||
#undef THREAD_STACK_SIZE | ||
#define THREAD_STACK_SIZE 0x100000 | ||
#endif | ||
#if THREAD_STACK_SIZE == -1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this |
||
#undef THREAD_STACK_SIZE | ||
/* This is big enough for most platforms without being wasteful. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we have a unittest in the stdlib that exercises the default recursion limit to on a thread to ensure the process doesn't crash? (it'll be imperfect as different internal call recursion codepaths have different C stack needs, but it still serves as a good failsafe; perhaps have the test raise recursionlimit to 1.5x its default value). https://github.com/python/cpython/blob/v3.10.0/Lib/test/test_threading.py#L1234 test_threading.test_recursion_limit exists. We should probably change that to raise the recursion limit a bit above the default in it's thread for some safety margin. |
||
#define THREAD_STACK_SIZE 0x200000 | ||
#endif | ||
|
||
/* for safety, ensure a viable minimum stacksize */ | ||
#define THREAD_STACK_MIN 0x8000 /* 32 KiB */ | ||
#else /* !_POSIX_THREAD_ATTR_STACKSIZE */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid disruption for anyone who may already be supplying CFLAGS containing -DTHREAD_STACK_SIZE=0 in their builds already keep the existing 0 behavior: 0 should be the platform specific values below.
If we want a new value in some circumstances, that should either be enabled via an appropriate test in
configure.ac
and thus via pyconfig.h. Or yet another platform specific compile time#if
check should be used here to detect musl libc.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be clear, the purpose here is to make the code universal. Right now, the only platform where the default thread size actually works is glibc. Instead of adding a case for each and every platform other than glibc, IMO it makes much more sense to have a sane default and override for one or two platforms as necessary, instead.
Testing for musl is unsupported, they don't provide any identifying macros, by design.