Skip to content

gh-153176: Fix destroy_interpreter() test helper clearing a non-current thread state#153307

Merged
kumaraditya303 merged 3 commits into
python:mainfrom
zangjiucheng:gh-153176-fix
Jul 24, 2026
Merged

gh-153176: Fix destroy_interpreter() test helper clearing a non-current thread state#153307
kumaraditya303 merged 3 commits into
python:mainfrom
zangjiucheng:gh-153176-fix

Conversation

@zangjiucheng

@zangjiucheng zangjiucheng commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #153176.

On free-threaded debug builds, _testinternalcapi.destroy_interpreter(id, basic=True)
aborted the process with:

Assertion `tstate == (_PyThreadStateImpl *)_PyThreadState_GET()' failed.

The root cause is in the test helper, not in obmalloc. destroy_interpreter()
calls PyThreadState_Clear(t1) / PyThreadState_Delete(t1) while t2 is the
current thread state. Clearing a non-current thread state runs
_PyThreadState_ClearMimallocHeaps(t1), and on a debug build
mi_heap_collect_ex() treats MI_ABANDON as >= MI_FORCE, so it calls
_mi_abandoned_reclaim_all() and reclaims abandoned pages back into t1's
heaps. That reaches _PyMem_mi_page_reclaimed(), where the reclaimed page
belongs to t1 but the current thread state is t2, so the assertion fires.

The assertion is correct — reclaim should only happen into the current thread's
own heap — so this keeps it and fixes the helper instead: t1 is left for
Py_EndInterpreter() to clean up, matching the rule that PyThreadState_Clear()
must be called on the current thread. Thanks @kumaraditya303 for pinpointing the
root cause.

Test plan

  • ./python -m test test_free_threading.test_interpreters -v
  • With the assertion in place, reproduced the abort on a free-threaded
    debug build before the fix; confirmed it no longer reproduces after.

@weixlu

weixlu commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

I also think we can just relax this assertion. Thanks for your fix!

Comment thread Objects/obmalloc.c Outdated
…ent thread state

_testinternalcapi.destroy_interpreter(basic=True) called PyThreadState_Clear()
and PyThreadState_Delete() on t1 while t2 was the current thread state. On a
free-threaded debug build this reclaimed mimalloc pages into a heap not owned
by the current thread, tripping the assertion in _PyMem_mi_page_reclaimed().

Leave t1 for Py_EndInterpreter() to clean up. Add a regression test.

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Co-authored-by: Xiaowei Lu <weixlu420302@gmail.com>
@kumaraditya303

Copy link
Copy Markdown
Contributor

The PR title and description needs to be updated.

Comment thread Misc/NEWS.d/next/Tests/2026-07-22-00-00-00.gh-issue-153176.mZ8nQ4.rst Outdated
@zangjiucheng zangjiucheng changed the title gh-153176: Fix crash in _PyMem_mi_page_reclaimed on free-threaded debug builds gh-153176: Fix destroy_interpreter() test helper clearing a non-current thread state Jul 23, 2026
@kumaraditya303
kumaraditya303 merged commit 6e98393 into python:main Jul 24, 2026
113 of 115 checks passed
@bedevere-bot

Copy link
Copy Markdown

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot s390x Fedora Stable LTO + PGO 3.x (tier-3) has failed when building commit 6e98393.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1627/builds/3097) and take a look at the build logs.
  4. Check if the failure is related to this commit (6e98393) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1627/builds/3097

Summary of the results of the build (if available):

Click to see traceback logs
Note: switching to '6e983938834a8b6c7043369b3c5de2b5d2084ea4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 6e983938834a8 gh-153176: Fix destroy_interpreter() test helper clearing a non-current thread state (#153307)
Switched to and reset branch 'main'

find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
make[2]: [Makefile:3474: clean-retain-profile] Error 1 (ignored)
./Modules/socketmodule.c: In function ‘getsockaddrarg’:
./Modules/socketmodule.c:2646:9: warning: ‘strncpy’ specified bound 64 equals destination size [-Wstringop-truncation]
 2646 |         strncpy((char *)sa->salg_name, name, sizeof(sa->salg_name));
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/ld.bfd: final link failed: No space left on device
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:1891: Programs/_freeze_module] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [Makefile:996: profile-gen-stamp] Error 2
make: *** [Makefile:1008: profile-run-stamp] Error 2

@bedevere-bot

Copy link
Copy Markdown

⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️

Hi! The buildbot s390x Fedora Stable LTO 3.x (tier-3) has failed when building commit 6e98393.

What do you need to do:

  1. Don't panic.
  2. Check the buildbot page in the devguide if you don't know what the buildbots are or how they work.
  3. Go to the page of the buildbot that failed (https://buildbot.python.org/#/builders/1654/builds/3074) and take a look at the build logs.
  4. Check if the failure is related to this commit (6e98393) or if it is a false positive.
  5. If the failure is related to this commit, please, reflect that on the issue and make a new Pull Request with a fix.

You can take a look at the buildbot page here:

https://buildbot.python.org/#/builders/1654/builds/3074

Summary of the results of the build (if available):

Click to see traceback logs
Note: switching to '6e983938834a8b6c7043369b3c5de2b5d2084ea4'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 6e983938834a8 gh-153176: Fix destroy_interpreter() test helper clearing a non-current thread state (#153307)
Switched to and reset branch 'main'

Assembler messages:
Fatal error: can't create Modules/resource.o: No space left on device
Assembler messages:
Fatal error: can't create Modules/_multiprocessing/posixshmem.o: No space left on device
make: *** [Makefile:3781: Modules/resource.o] Error 1
make: *** Waiting for unfinished jobs....
make: *** [Makefile:3791: Modules/_multiprocessing/posixshmem.o] Error 1
/tmp/ccTKtqke.s: Assembler messages:
/tmp/ccTKtqke.s: Fatal error: can't write 332 bytes to section .text of Modules/expat/xmlparse.o: 'No space left on device'
Assembler messages:
Fatal error: can't create Modules/termios.o: No space left on device
make: *** [Makefile:3789: Modules/termios.o] Error 1
/tmp/cc8EHqEG.s: Assembler messages:
Fatal error: can't create Modules/syslogmodule.o: No space left on device
Assembler messages:
/tmp/cc8EHqEG.s: Fatal error: can't write 3951 bytes to section .gnu.lto_packed_name_dawg.83.a1122b6197080a2a of Modules/unicodedata.o: 'No space left on device'
make: *** [Makefile:3787: Modules/syslogmodule.o] Error 1
/tmp/ccTKtqke.s: Fatal error: Modules/expat/xmlparse.o: No such file or directory
make: *** [Makefile:1614: Modules/expat/xmlparse.o] Error 1
/tmp/cc8EHqEG.s: Fatal error: Modules/unicodedata.o: No such file or directory
make: *** [Makefile:3771: Modules/unicodedata.o] Error 1
/tmp/ccYg48Cu.s: Assembler messages:
/tmp/ccYg48Cu.s: Fatal error: can't write 3952 bytes to section .gnu.debuglto_.debug_info of Modules/selectmodule.o: 'No space left on device'
/tmp/ccvInZys.s: Assembler messages:
/tmp/ccvInZys.s: Fatal error: Modules/mmapmodule.o: No space left on device
make: *** [Makefile:3777: Modules/mmapmodule.o] Error 1
make: *** [Makefile:3783: Modules/selectmodule.o] Error 1
/tmp/cc8yXini.s: Assembler messages:
/tmp/cc8yXini.s: Fatal error: can't write 3951 bytes to section .gnu.lto_.decls.eddbfbeabee625fb of Modules/socketmodule.o: 'No space left on device'
/tmp/cc8yXini.s: Fatal error: Modules/socketmodule.o: No such file or directory
make: *** [Makefile:3785: Modules/socketmodule.o] Error 1

find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
find: ‘build’: No such file or directory
make: [Makefile:3474: clean-retain-profile] Error 1 (ignored)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion triggered in MiMalloc (free-threaded build)

5 participants