GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-141044: Fix ASan leak with small threading.stack_size() by KingLizard1020 · Pull Request #157691 · python/cpython

Conversation

@KingLizard1020

@KingLizard1020 KingLizard1020 commented Sep 17, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Fix a LeakSanitizer / reference leak when creating a threading.Thread after threading.stack_size() is set to a small value (the reported repro used 127 KiB and did not join).

Issue: #141044

Diagnosis

This is a real reference leak, not an LSan false positive. With a debug + AddressSanitizer build:

  • threading.stack_size(127 * 1024) followed by Thread.start() (with or without join()) leaks Thread / _ThreadHandle / Context objects.
  • Default stack size / 256 KiB do not leak.
  • _thread.start_new_thread() at 127 KiB does not leak; threading.Thread does, because bootstrap runs _context.run(self.run) then finally: self._delete().

C stack overflow protection (gh-130396) reserves soft/hard margins at the bottom of each thread stack. Under ASan, instrumentation consumes extra C frames, so the old 3-margin minimum left almost no working space above the soft limit. At 127 KiB, _testinternalcapi.get_c_recursion_remaining() was already ~50 and bootstrap failed to finish cleanup.

The new test_stack_size_no_leak also failed on Py_DEBUG (non-ASan) CI at the old 3-margin floor (~102 KiB): eight threads still leaked ~355 refs. Clean from ~139 KiB upward; 6 margins (~200 KiB) is clean.

3.13 did not use pthread_getattr_np stack limits, which is why it showed no leak.

Fix

When built with Py_DEBUG, AddressSanitizer, ThreadSanitizer, or UndefinedBehaviorSanitizer (same set as _PyOS_LOG2_STACK_MARGIN), require 6 stack margins for _PyOS_MIN_STACK_SIZE. Release builds stay at 3. Reasons differ and are documented in the header: TSan only uses half the stack in tstate_set_stack(); ASan/debug need extra room for instrumentation / checked builds. _thread.stack_size() already rejects sizes below _PyOS_MIN_STACK_SIZE + SYSTEM_PAGE_SIZE, so 127 KiB is now a ValueError on those builds (~200704 byte minimum on this builder).

Tests

  • test_thread.ThreadRunningTests.test_stack_size: ASan/debug ValueError for 127 * 1024, and a failed set must leave size at 0.
  • test_threading.ThreadTests.test_stack_size_no_leak: original unjoined 127 KiB repro (exits cleanly when rejected), unjoined + joined threads at the new minimum with gettotalrefcount() and ASAN_OPTIONS=detect_leaks=1.

Verification

Built with ./configure --with-address-sanitizer --with-pydebug && make -j, and separately with pydebug alone.

Before: LSan / refcount leaks on the issue reproducer and on the new minimum under Py_DEBUG. After: threading.stack_size(127 * 1024) raises ValueError where the floor applies; threads at the new minimum are clean under refcount + LSan (joined and unjoined).

Local: ./python -m test test_thread test_threading -v -m '*stack_size*' → SUCCESS.

  • Issue: memory leak in threading stack size #141044

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@KingLizard1020
KingLizard1020 requested a review from ericsnowcurrently as a code owner September 17, 2026 16:59
@bedevere-app bedevere-app Bot mentioned this pull request Sep 17, 2026
memory leak in threading stack size #141044
Open
@bedevere-app bedevere-app Bot added the awaiting review label Sep 17, 2026
@KingLizard1020
KingLizard1020 requested review from AA-Turner, JacobCoffee, ezio-melotti, hugovk, itamaro and webknjaz as code owners September 17, 2026 17:34
@KingLizard1020
pythongh-141044: Fix ASan leak with small threading.stack_size()
00fe666
AddressSanitizer instrumentation consumes extra C stack, so the old
minimum left no working space above the soft recursion limit.
threading.Thread bootstrap then leaked thread objects. Require 6 stack
margins under ASan, matching TSan. Cover the unjoined original repro
and confirm the new minimum does not leak. Move the NEWS blurb to
Library, matching pythongh-143191.
@github-actions
github-actions Bot force-pushed the cursor/fix-threading-stack-size-leak-a999 branch from 1f5b1e7 to 00fe666 Compare September 17, 2026 17:36
@hugovk
hugovk removed request for AA-Turner, JacobCoffee, ezio-melotti, hugovk, itamaro and webknjaz September 18, 2026 10:19
@hugovk hugovk mentioned this pull request Sep 18, 2026
gh-157217: Fix dir() race when merging from a mappingproxy #157279
Open
KingLizard1020 added 12 commits September 21, 2026 13:15
@KingLizard1020
pythongh-141044: Require 6 stack margins on debug builds too
3aef310
Py_DEBUG (and UBSan) share the larger stack margin with ASan/TSan, but
still used a 3-margin minimum. threading.Thread bootstrap then leaked
references at that floor; the new refcount test failed on Ubuntu/macOS
CI. Align the minimum with ASan/TSan. Release builds stay at 3 margins.
@KingLizard1020
pythongh-141044: Update NEWS for debug/sanitizer 6-margin floor
09dc0cb
@KingLizard1020
pythongh-141044: Portable 127 KiB stack_size rejection check
04ebedb
@KingLizard1020
pythongh-141044: Restore test_thread.py (undo accidental PLACEHOLDER)
bfbf64c
@KingLizard1020
pythongh-141044: Silence NEWS Sphinx nit for _thread.stack_size
7f942ca
@KingLizard1020
pythongh-141044: Raise TSan stack_size floor to 12 margins
1fac29a
TSan only uses half the stack in tstate_set_stack(), so the 6-margin
minimum that is enough for ASan/debug still leaked Thread objects at
the floor under ThreadSanitizer (refcount delta ~355). Require 12
margins for TSan. Update tests that assumed 256 KiB is always accepted.
@KingLizard1020
pythongh-141044: Update NEWS for TSan 12-margin stack_size floor
0f0971d
@KingLizard1020
pythongh-141044: Allow stack_size tests to skip 256 KiB under TSan
f2242a1
@KingLizard1020
pythongh-141044: Skip 256 KiB stack tests when below TSan floor
4d72b7e
@KingLizard1020
temp: canary for restore path (will remove)
c15bbbd
@KingLizard1020
temp: escape-test canary (will remove)
ab3acf1
@KingLizard1020
wip: restore test_threading.py (5KB partial)
c43e6b8
KingLizard1020 added 4 commits September 21, 2026 15:29
@KingLizard1020
temp: remove restore canary
d012c29
@KingLizard1020
test @file
12213d2
@KingLizard1020
wip: restore test_threading.py (5KB partial, undo @path probe)
bb6fe83
@KingLizard1020
pythongh-141044: Fix Docs soft-deprecated KeyError in changes builder
124b140
Docs CI checks out the PR head, so register soft-deprecated and deprecated-removed in ChangesBuilder.typemap (pythongh-155095).
@KingLizard1020
KingLizard1020 requested a review from StanFromIreland as a code owner September 21, 2026 21:33
KingLizard1020 added 5 commits September 21, 2026 15:33
@KingLizard1020
Add cpy test_threading restore part _cpy_tt_part_0.b64 (no trigger)
f609ce4
@KingLizard1020
Add cpy test_threading restore part _cpy_tt_part_1.b64 (no trigger)
fe78d4b
@KingLizard1020
Fix part1 chunk0 of cpy test_threading restore
4eb90e5
@KingLizard1020
Restore threading regression tests and update from main
6222f46
@KingLizard1020
Fix threading tests for sanitizer stack minimum
de3886e
@StanFromIreland
StanFromIreland removed their request for review September 23, 2026 07:34
KingLizard1020 and others added 3 commits September 23, 2026 10:46
@KingLizard1020
Merge upstream main into PR python#157691
be750c5
@KingLizard1020
Merge branch 'main' into cursor/fix-threading-stack-size-leak-a999
af31989
@KingLizard1020
Merge remote-tracking branch 'upstream/main' into cursor/fix-threadin…
db9370d
…g-stack-size-leak-a999
@python-cla-bot

python-cla-bot Bot commented Oct 5, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting review

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@KingLizard1020
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.