Repository navigation
fix(initimg): keep glibc's reported main stack size near RLIMIT_STACK - #62
Conversation
bcc5636 to
efc8a0a
Compare
Merging this PR will not alter performance
Comparing Footnotes
|
[Medium impact] The change affects main-stack setup for Linux programs launched under Valgrind. Fix the Darwin stack-size calculation before merging; it breaks DRD startup.
|
efc8a0a to
a67fed7
Compare
glibc's pthread_getattr_np computes the main thread's stack size as RLIMIT_STACK minus the distance from __libc_stack_end to the end of the mapping containing it. Since the fixed startup stack layout pinned SP 8 MiB below the top of that mapping, glibc subtracted the whole region and reported a 4 KiB main stack at the default 8 MiB limit. CPython 3.14 derives its C-stack guard from that size and failed at startup with BufferError. Split the startup image in two mappings: the argv/env/auxv strings grow upward from a fixed strings_start in their own anonymous mapping, and only the pointer tables (64 KiB, TABLES_REGION_SZB) stay above SP in the stack mapping. An unmapped, reserved page between them keeps the kernel from merging the two VMAs. glibc now reports RLIMIT_STACK minus 64 KiB (natively about 100 KiB), while SP, strings_start and the reservation bottom stay fixed for any argument and environment size. Tables larger than one granule take whole granules from the string mapping without moving SP. The main thread's client_stack_szB is now derived from the segment that holds SP instead of clstack_max_size, so the overflow message and the setrlimit comparison no longer count the string mapping. Add none/tests/linux/main_stack_attr, which checks that the reported range covers SP and is within 1 MiB of RLIMIT_STACK, then re-executes itself with 20000 arguments to exercise the table fallback under --trace-children=yes. It fails on the previous layout and passes natively.
a67fed7 to
ab3ed5c
Compare
Since 0codspeed12, glibc reported the main thread stack as 4 KiB under valgrind at the default `ulimit -s`, so Python 3.14 failed at startup with a BufferError. The new package reports a size close to RLIMIT_STACK again (CodSpeedHQ/valgrind-codspeed#62). Refs COD-4123 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
TLDR: Since #53 glibc reported a 4 KiB main thread stack at the default 8 MiB limit, which breaks CPython 3.14 (
BufferErrorat startup). The startup strings now live in their own mapping so only 64 KiB sits above SP in the stack mapping; glibc reportsRLIMIT_STACK - 64 KiB(native:- ~100 KiB), SP stays fixed.Layout (
initimg-linux.c)pthread_getattr_npcomputesRLIMIT_STACK - (end of VMA containing SP - SP). The fixed 8 MiB region from fix(initimg): stabilize Linux startup stack layout #53 was all inside that VMA.strings_startin a separate anonymous mapping; argc/argv/envp/auxv tables (64 KiB granule) stay above SP. One reserved, unmapped page between the two keeps the kernel from merging the VMAs.szB + 8 MiBand growth-on-fault are unchanged.m_main.cclient_stack_szBis now sized from the segment holding SP instead ofclstack_max_size, so the overflow message andsetrlimitcomparison no longer include the string mapping.Test
none/tests/linux/main_stack_attr: reported range must cover SP and be within 1 MiB of an 8 MiB limit; then re-execs itself with 20000 args under--trace-children=yesto cover the granule fallback. Fails on master (SP ... outside reported stack [.., ..+4 KiB)), passes natively.Measured (8 MiB
ulimit -s, x86_64)BufferErrornone/tests/linux: 18/19 pass;getdents_filterfails on master too.memcheck/tests/linux: 27/28,sys-execveatfails on master too. memcheck, helgrind and drd run a program that reads all ofargv[]andenvironwithout reports.Review notes
argv/envpstrings are no longer inside the[stack]VMA. Visible only through/proc/self/maps; in-place argv rewriting still works (mapping is RW).ulimit -s 64Mreports 64 MiB while usable depth is clamped to 16 MiB; runtimesetrlimitdoes not grow the reservation.COD-4117