Title: gh-148613: Fix race in `gc_set_threshold` and `gc_get_threshold` by LindaSummer · Pull Request #150356 · python/cpython · GitHub
Open Graph Title: gh-148613: Fix race in `gc_set_threshold` and `gc_get_threshold` by LindaSummer · Pull Request #150356 · python/cpython
X Title: gh-148613: Fix race in `gc_set_threshold` and `gc_get_threshold` by LindaSummer · Pull Request #150356 · python/cpython
Description: Issue gh-148613 Root Cause In free-threading, the gc_generation.threshold races in threads when one thread has objects triggered the GC. cpython/Python/gc_free_threading.c Lines 2025 to 2031 in cb72193 if (gc->alloc_count >= LOCAL_ALLOC_COUNT_THRESHOLD) { // TODO: Use Py_ssize_t for the generation count. GCState *gcstate = &tstate->interp->gc; _Py_atomic_add_int(&gcstate->young.count, (int)gc->alloc_count); gc->alloc_count = 0; if (gc_should_collect(gcstate) && Inside gc_should_collect we read the gcstate->young.threshold and gcstate->old[0].threshold without thread syncing. cpython/Python/gc_free_threading.c Lines 1996 to 2004 in cb72193 gc_should_collect(GCState *gcstate) { int count = _Py_atomic_load_int_relaxed(&gcstate->young.count); int threshold = gcstate->young.threshold; int gc_enabled = _Py_atomic_load_int_relaxed(&gcstate->enabled); if (count <= threshold || threshold == 0 || !gc_enabled) { return false; } if (gcstate->old[0].threshold == 0) { At the same time, the threshold setting also has no syncing protection. cpython/Modules/gcmodule.c Lines 170 to 175 in cb72193 gcstate->young.threshold = threshold0; if (group_right_1) { gcstate->old[0].threshold = threshold1; } if (group_right_2) { gcstate->old[1].threshold = threshold2; This explains why a cyclic referenced object caused this TSAN report. The cyclic object couldn't make ref count to zero in scoped call stack, and it increments the _gc_thread_state.alloc_count to LOCAL_ALLOC_COUNT_THRESHOLD. Then the GC collect triggered in this thread and races with another thread's update of gc_generation.threshold. Proposed Changes Add relaxed atomic load/store protection for the gc_generation.threshold setter and getter.
Open Graph Description: Issue gh-148613 Root Cause In free-threading, the gc_generation.threshold races in threads when one thread has objects triggered the GC. cpython/Python/gc_free_threading.c ...
X Description: Issue gh-148613 Root Cause In free-threading, the gc_generation.threshold races in threads when one thread has objects triggered the GC. cpython/Python/gc_free_threading.c ...
Opengraph URL: https://github.com/python/cpython/pull/150356
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:df87ea50-87d0-08d4-1022-7557edd92e3e |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | E290:1D4CDD:1F0125:2B0F78:6A59C36E |
| html-safe-nonce | 92b9f0823fdcd49166d90daa8d578bf0c6340c813951d44ae6594ad2d173afda |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFMjkwOjFENENERDoxRjAxMjU6MkIwRjc4OjZBNTlDMzZFIiwidmlzaXRvcl9pZCI6IjEwMTU1NjQyOTkwMzE2NTkzNzQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 1cc25d39627d7c3a73a8f10578da213b50d70f3f80e0b464b969efb10464a520 |
| hovercard-subject-tag | pull_request:3738092019 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,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/python/cpython/pull/150356/files |
| twitter:image | https://avatars.githubusercontent.com/u/14014471?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/14014471?s=400&v=4 |
| og:image:alt | Issue gh-148613 Root Cause In free-threading, the gc_generation.threshold races in threads when one thread has objects triggered the GC. cpython/Python/gc_free_threading.c ... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | ba3976babb66479b1c943a8edc0777d96157da48fadc0161f9ddb219deee8353 |
| turbo-cache-control | no-preview |
| diff-view | unified |
| 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 full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | ab680789ae4a316cdaf0d5a292a1760140931cc4 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width