Title: free-threading: PyImport_AddModuleRef race condition · Issue #137422 · python/cpython · GitHub
Open Graph Title: free-threading: PyImport_AddModuleRef race condition · Issue #137422 · python/cpython
X Title: free-threading: PyImport_AddModuleRef race condition · Issue #137422 · python/cpython
Description: Bug report Bug description: On a NoGIL interpreter, if two threads call PyImport_AddModuleRef for the same module name at the same time, and that module does not exist yet, it is possible that the two calls to the function return two dif...
Open Graph Description: Bug report Bug description: On a NoGIL interpreter, if two threads call PyImport_AddModuleRef for the same module name at the same time, and that module does not exist yet, it is possible that the ...
X Description: Bug report Bug description: On a NoGIL interpreter, if two threads call PyImport_AddModuleRef for the same module name at the same time, and that module does not exist yet, it is possible that the ...
Opengraph URL: https://github.com/python/cpython/issues/137422
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"free-threading: PyImport_AddModuleRef race condition","articleBody":"# Bug report\n\n### Bug description:\n\nOn a NoGIL interpreter, if two threads call [PyImport_AddModuleRef](https://github.com/python/cpython/blob/a50822ff94ae0625f0b46480857fb141531c0688/Python/import.c#L339) for the same module name at the same time, and that module does not exist yet, it is possible that the two calls to the function return two different objects, only one of which is stored in `sys.modules`.\n\nThe race condition is actually in the helper function import_add_module:\nhttps://github.com/python/cpython/blob/a50822ff94ae0625f0b46480857fb141531c0688/Python/import.c#L319-L335\nif both threads call `PyMapping_GetOptionalItem` before either has called `PyObject_SetItem`, you will get two different modules.\n\n## Context\nEach SWIG module calls `PyImport_AddModuleRef` to retrieve or initialise a shared global state module with the hardcoded name `swig_runtime_data5`, and then stores its pointer in a module-local global variable.\n\nSWIG is actually immune from this race condition because the call to `PyImport_AddModuleRef` always happens inside `SWIG_init`, which is an alias for `PyInit_\u003cmodulename\u003e` which holds the GIL.\n\nThis race condition only affects lazy initialisation patterns, where `PyImport_AddModuleRef` is executed for the first time after module init.\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\n_No response_\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-141822\n* gh-141830\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/crusaderky","@type":"Person","name":"crusaderky"},"datePublished":"2025-08-05T15:24:12.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":4},"url":"https://github.com/137422/cpython/issues/137422"}
| 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:464da94f-39af-6e1b-6342-5fe9abb3b2c1 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D50E:1FFDFF:542D534:76F81F1:6A4FFA93 |
| html-safe-nonce | ad303bec919ef7cf753cb4a6b83cf27f6dd433efe67bb84617723eea18d0e4ee |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENTBFOjFGRkRGRjo1NDJENTM0Ojc2RjgxRjE6NkE0RkZBOTMiLCJ2aXNpdG9yX2lkIjoiNjE0NzIxMjU3MDI3OTI3OTI1MSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 1b248de1f203d6be9e7c782cd02a9fe702a0f3ad99568dd976c32bed980beb69 |
| hovercard-subject-tag | issue:3293535587 |
| 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/137422/issue_layout |
| twitter:image | https://opengraph.githubassets.com/3bc603276e8161b252757a5126cbe0cd15d1c01269d8138442717b334b4fc34a/python/cpython/issues/137422 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/3bc603276e8161b252757a5126cbe0cd15d1c01269d8138442717b334b4fc34a/python/cpython/issues/137422 |
| og:image:alt | Bug report Bug description: On a NoGIL interpreter, if two threads call PyImport_AddModuleRef for the same module name at the same time, and that module does not exist yet, it is possible that the ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | crusaderky |
| hostname | github.com |
| expected-hostname | github.com |
| None | 3bd0ff5d28a87b4801a63fb38c2a21a91b0a700dca159dc9416aeae05771b899 |
| 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 | 67a336083e4dcb40224dc2c01cd4c7ed413bdb09 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width