Title: GC in free-threaded build has problems with `Py_INCREF()`/`Py_DECREF()` in `tp_traverse` handlers · Issue #123241 · python/cpython · GitHub
Open Graph Title: GC in free-threaded build has problems with `Py_INCREF()`/`Py_DECREF()` in `tp_traverse` handlers · Issue #123241 · python/cpython
X Title: GC in free-threaded build has problems with `Py_INCREF()`/`Py_DECREF()` in `tp_traverse` handlers · Issue #123241 · python/cpython
Description: Bug report This came up in the context of nanobind. Nanobind implements (in a test) a traverse function: int funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) { FuncWrapper *w = nb::inst_ptr
Open Graph Description: Bug report This came up in the context of nanobind. Nanobind implements (in a test) a traverse function: int funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) { FuncWrapper *w = n...
X Description: Bug report This came up in the context of nanobind. Nanobind implements (in a test) a traverse function: int funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) { FuncWrapper *w = n...
Opengraph URL: https://github.com/python/cpython/issues/123241
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"GC in free-threaded build has problems with `Py_INCREF()`/`Py_DECREF()` in `tp_traverse` handlers","articleBody":"# Bug report\n\nThis came up in the context of [nanobind](https://github.com/wjakob/nanobind/). Nanobind implements (in a test) a traverse function:\n\n```c++\nint funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) {\n FuncWrapper *w = nb::inst_ptr\u003cFuncWrapper\u003e(self);\n\n nb::object f = nb::cast(w-\u003ef, nb::rv_policy::none);\n Py_VISIT(f.ptr());\n\n return 0;\n};\n```\n\nThe ``nb::object`` smart pointer is internally reference counted. In other words, the above is roughly equivalent to:\n\n```c\nint funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) {\n PyObject *f = self-\u003ew-\u003ef;\n Py_INCREF(f);\n Py_VISIT(f);\n Py_DECREF(f);\n return 0;\n};\n```\n\nThis leads to a leak in the free-threaded GC for subtle reasons: when determining resurrected objects, the free-threaded GC uses `ob_ref_local` to compute the refcount - incoming references, which may be (temporarily) negative. In this case, `Py_INCREF()` adds 1 to the refcount, but by the time `Py_DECREF()` is called, the local refcount is `-1` which makes the object appear immortal.\n\nThere are a number of limitations on the implementations of traverse functions, which are not well documented. For example, it's not safe to allocate, free, track, or untrack Python objects. It's unclear to me whether there are other issues with calling refcounting functions in traverse callbacks.\n\nI think we can make [`handle_resurrected_objects`](https://github.com/python/cpython/blob/297f2e093ec95800ae2184330b8408c875523467/Python/gc_free_threading.c#L974) more robust to this by splitting the first pass over `state-\u003eunreachable` into two passes.\n\nSee also: https://github.com/PyO3/pyo3/issues/3165, which was not related to the free-threaded build.\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-142232\n* gh-142271\n* gh-142272\n* gh-142422\n* gh-142423\n* gh-142567\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/colesbury","@type":"Person","name":"colesbury"},"datePublished":"2024-08-22T19:28:14.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":11},"url":"https://github.com/123241/cpython/issues/123241"}
| 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:495f42a6-5f8c-20ab-4deb-19430f575d06 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E3BE:1587BA:825556C:AC5FB44:696DEF75 |
| html-safe-nonce | b0106a19d30d203b25010967aa347e392cb5f68ff6fca21ae39b88a28426650e |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFM0JFOjE1ODdCQTo4MjU1NTZDOkFDNUZCNDQ6Njk2REVGNzUiLCJ2aXNpdG9yX2lkIjoiNDY5Mzc2NjkyNDE4MTEzMzk3IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 4388d9ebce3f65c1211777f3e0ffb034d27114e641563121d3f97993c9cc7ac0 |
| hovercard-subject-tag | issue:2481556211 |
| 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/123241/issue_layout |
| twitter:image | https://opengraph.githubassets.com/03dc4f701d8e3097693eae206a96ab3ee4772a35bab6ab10d5aee4bcb8b0bde0/python/cpython/issues/123241 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/03dc4f701d8e3097693eae206a96ab3ee4772a35bab6ab10d5aee4bcb8b0bde0/python/cpython/issues/123241 |
| og:image:alt | Bug report This came up in the context of nanobind. Nanobind implements (in a test) a traverse function: int funcwrapper_tp_traverse(PyObject *self, visitproc visit, void *arg) { FuncWrapper *w = n... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | colesbury |
| hostname | github.com |
| expected-hostname | github.com |
| None | 4922b452d03cd8dbce479d866a11bc25b59ef6ee2da23aa9b0ddefa6bd4d0064 |
| 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 | 7e5ae23c70136152637ceee8d6faceb35596ec46 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width