Title: Data race between `gc_should_collect` and `gc_set_threshold_impl` · Issue #148613 · python/cpython · GitHub
Open Graph Title: Data race between `gc_should_collect` and `gc_set_threshold_impl` · Issue #148613 · python/cpython
X Title: Data race between `gc_should_collect` and `gc_set_threshold_impl` · Issue #148613 · python/cpython
Description: Bug report Bug description: gc_set_threshold_impl writes gcstate->young.threshold cpython/Modules/gcmodule.c Lines 154 to 161 in 69e0a78 static PyObject * gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1, int thr...
Open Graph Description: Bug report Bug description: gc_set_threshold_impl writes gcstate->young.threshold cpython/Modules/gcmodule.c Lines 154 to 161 in 69e0a78 static PyObject * gc_set_threshold_impl(PyObject *module, in...
X Description: Bug report Bug description: gc_set_threshold_impl writes gcstate->young.threshold cpython/Modules/gcmodule.c Lines 154 to 161 in 69e0a78 static PyObject * gc_set_threshold_impl(PyObject *module,...
Opengraph URL: https://github.com/python/cpython/issues/148613
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Data race between `gc_should_collect` and `gc_set_threshold_impl`","articleBody":"# Bug report\n\n### Bug description:\n\n`gc_set_threshold_impl` writes `gcstate-\u003eyoung.threshold`\nhttps://github.com/python/cpython/blob/69e0a78e6edc3166c7a5b166955c0cefd1bacd5d/Modules/gcmodule.c#L154-L161\n\nwhile `gc_should_collect()` reads `gcstate-\u003eyoung.threshold` non atomically\nhttps://github.com/python/cpython/blob/69e0a78e6edc3166c7a5b166955c0cefd1bacd5d/Python/gc_free_threading.c#L2198-L2203\n\nReproducer:\n\n```python\nimport sys\nimport gc\nfrom threading import Thread, Barrier\n\nclass C:\n pass\n\nN_THREADS = 8\nN_ITERS = 100_000\nbarrier = Barrier(N_THREADS)\n\ndef allocator():\n barrier.wait()\n keep = []\n for i in range(N_ITERS):\n a = C(); b = C()\n a.r = b; b.r = a\n if i % 100 == 0:\n keep.append(a)\n if len(keep) \u003e 1000:\n keep.clear()\n\ndef setter():\n barrier.wait()\n for i in range(N_ITERS):\n gc.set_threshold(100 + (i \u0026 0x3F), 10, 10)\n\nthreads = [Thread(target=allocator) for _ in range(N_THREADS - 1)]\nthreads.append(Thread(target=setter))\nfor t in threads: t.start()\nfor t in threads: t.join()\n```\n\nTSAN Report:\n```\nWARNING: ThreadSanitizer: data race (pid=482463)\n Read of size 4 at 0x555555e38f80 by thread T5:\n #0 gc_should_collect_mem_usage /cpython/Python/gc_free_threading.c:2168:36 (python3.15t+0x4a90c3) \n #1 gc_should_collect /cpython/Python/gc_free_threading.c:2217:12 (python3.15t+0x4a90c3)\n #2 record_allocation /cpython/Python/gc_free_threading.c:2234:13 (python3.15t+0x4a8324) \n #3 _PyObject_GC_Link /cpython/Python/gc_free_threading.c:2914:5 (python3.15t+0x4a8324)\n #4 _PyType_AllocNoTrack /cpython/Objects/typeobject.c:2537:9 (python3.15t+0x322b3d) \n #5 PyType_GenericAlloc /cpython/Objects/typeobject.c:2558:21 (python3.15t+0x32291e) \n #6 object_new /cpython/Objects/typeobject.c:7340:21 (python3.15t+0x32ed3b) \n #7 type_call /cpython/Objects/typeobject.c:2471:11 (python3.15t+0x32a7e2) \n #8 _PyObject_MakeTpCall /cpython/Objects/call.c:242:18 (python3.15t+0x20ef0f) \n #9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:142:16 (python3.15t+0x20fcf7) \n #10 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fcf7)\n #11 _Py_VectorCall_StackRefSteal /cpython/Python/ceval.c:733:11 (python3.15t+0x428ab9) \n #12 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4344:35 (python3.15t+0x435c37) \n #13 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) \n #14 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660)\n #15 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) \n #16 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) \n #17 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9)\n #18 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) \n #19 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x480a91) \n #20 context_run /cpython/Python/context.c:727:29 (python3.15t+0x480a91)\n #21 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x229fe7) \n #22 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x20fc33) \n #23 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fc33)\n #24 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42928c) \n #25 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1841:35 (python3.15t+0x42f07c) \n #26 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) \n #27 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660)\n #28 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) \n #29 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) \n #30 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9)\n #31 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) \n #32 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x20ff3b) \n #33 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x20ff3b)\n #34 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x20ffa5) \n #35 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x605bc2) \n #36 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x535427) \n Previous write of size 4 at 0x555555e38f80 by thread T8:\n #0 gc_set_threshold_impl /cpython/Modules/gcmodule.c:161:30 (python3.15t+0x5510f6) \n #1 gc_set_threshold /cpython/Modules/clinic/gcmodule.c.h:266:20 (python3.15t+0x5510f6)\n #2 cfunction_call /cpython/Objects/methodobject.c:575:18 (python3.15t+0x2c10d1) \n #3 _PyObject_MakeTpCall /cpython/Objects/call.c:242:18 (python3.15t+0x20ef0f) \n #4 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:142:16 (python3.15t+0x20fcf7) \n #5 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fcf7)\n #6 _Py_VectorCall_StackRefSteal /cpython/Python/ceval.c:733:11 (python3.15t+0x428ab9) \n #7 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4344:35 (python3.15t+0x435c37) \n #8 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) \n #9 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660)\n #10 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) \n #11 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) \n #12 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9)\n #13 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) \n #14 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x480a91) \n #15 context_run /cpython/Python/context.c:727:29 (python3.15t+0x480a91)\n #16 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x229fe7) \n #17 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x20fc33) \n #18 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fc33)\n #19 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42928c) \n #20 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1841:35 (python3.15t+0x42f07c) \n #21 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) \n #22 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660)\n #23 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) \n #24 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) \n #25 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9)\n #26 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) \n #27 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x20ff3b) \n #28 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x20ff3b)\n #29 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x20ffa5) \n #30 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x605bc2) \n #31 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x535427) \n\n Location is global '_PyRuntime' of size 405120 at 0x555555e108c0 (python3.15t+0x8e4f80)\n```\n\n\n\n\n\n### CPython versions tested on:\n\nPython 3.15.0a8+ free-threading build (heads/main:44f1b987ed1, Apr 14 2026, 07:56:49)\n\n### Operating systems tested on:\n\nUbuntu\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-150356\n* gh-150841\n* gh-150842\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/Naserume","@type":"Person","name":"Naserume"},"datePublished":"2026-04-15T12:41:06.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/148613/cpython/issues/148613"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:f86ab030-6f65-eab5-77b5-1042b7e5709d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D6BC:1DE3C:37C1A:4B156:6A57AA68 |
| html-safe-nonce | e38ee3a0a2665a461a4c27e9343ceef21d84102ad0e1b3a6a507077689407282 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENkJDOjFERTNDOjM3QzFBOjRCMTU2OjZBNTdBQTY4IiwidmlzaXRvcl9pZCI6IjIwMDcxODAyODgxMzMxNDcyNDAiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | d005813e92ed036e478d4f75b2656509afd16190e436dc58ae69dd5dcb22364d |
| hovercard-subject-tag | issue:4268976994 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/148613/issue_layout |
| twitter:image | https://opengraph.githubassets.com/949a0c19d7d31c907782fcd48c8558c9bc159e8c00f0c1302cabaebde7893de7/python/cpython/issues/148613 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/949a0c19d7d31c907782fcd48c8558c9bc159e8c00f0c1302cabaebde7893de7/python/cpython/issues/148613 |
| og:image:alt | Bug report Bug description: gc_set_threshold_impl writes gcstate->young.threshold cpython/Modules/gcmodule.c Lines 154 to 161 in 69e0a78 static PyObject * gc_set_threshold_impl(PyObject *module, in... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Naserume |
| hostname | github.com |
| expected-hostname | github.com |
| None | 017a07c29bdd8a37b5907fc9a689338deb7103b5af7f56714193b2700229b3df |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 4cd16a676f89d1cedb932671a5c2d20b8e60f86a |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width