Title: ThreadSanitizer: data race in _struct module initialization with InterpreterPoolExecutor (free-threading build) · Issue #140260 · python/cpython · GitHub
Open Graph Title: ThreadSanitizer: data race in _struct module initialization with InterpreterPoolExecutor (free-threading build) · Issue #140260 · python/cpython
X Title: ThreadSanitizer: data race in _struct module initialization with InterpreterPoolExecutor (free-threading build) · Issue #140260 · python/cpython
Description: Bug report Bug description: ThreadSanitizer detects a data race when using InterpreterPoolExecutor with the free-threading build. Multiple threads simultaneously write to the global variable lilendian_table in the _struct module during m...
Open Graph Description: Bug report Bug description: ThreadSanitizer detects a data race when using InterpreterPoolExecutor with the free-threading build. Multiple threads simultaneously write to the global variable lilend...
X Description: Bug report Bug description: ThreadSanitizer detects a data race when using InterpreterPoolExecutor with the free-threading build. Multiple threads simultaneously write to the global variable lilend...
Opengraph URL: https://github.com/python/cpython/issues/140260
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"ThreadSanitizer: data race in _struct module initialization with InterpreterPoolExecutor (free-threading build)","articleBody":"# Bug report\n\n### Bug description:\n\nThreadSanitizer detects a data race when using `InterpreterPoolExecutor` with the free-threading build. Multiple threads simultaneously write to the global variable `lilendian_table` in the `_struct` module during module initialization.\n\nThe race occurs at:\n- **Thread T1 and T2**: Both write to `lilendian_table` at `_structmodule_exec` (lines 2745:31 and 2746:33)\n- **Location**: `global 'lilendian_table' of size 840 at 0x7ffff4513ca0` in `_struct.cpython-315td-x86_64-linux-gnu.so`\n\nBoth threads are executing through `InterpreterPoolExecutor`, importing modules in separate subinterpreters, which triggers concurrent initialization of the `_struct` extension module.\n\n### How to Reproduce\n\n**Build configuration:**\n```bash\nCC=clang CXX=clang++ ./configure --with-thread-sanitizer --with-pydebug --enable-experimental-jit=yes --with-lto=full --with-tail-call-interp --disable-gil\nmake -j\n```\n\n**Run command:**\n```bash\nTSAN_OPTIONS=handle_segv=0 ./python -X dev -X showrefcount bug.py\n```\n\n**Test script (bug.py):**\n```python\nfrom concurrent.futures import InterpreterPoolExecutor\nfrom functools import lru_cache\n\n@lru_cache(maxsize=512)\ndef fib(n):\n \"\"\"Function that JIT will compile\"\"\"\n if n \u003c 2:\n return n\n return fib(n-1) + fib(n-2)\n\nif __name__ == '__main__':\n with InterpreterPoolExecutor() as t:\n for i in range(2):\n t.submit(fib, i)\n```\n\n**Note:** The race occurs with any loop iteration count (range(1), range(2), etc.)\n\n### TSAN Output\n\n[log.txt](https://github.com/user-attachments/files/22975650/log.txt)\n\n### Environment\n\n- **CPython version**: main branch\n- **Operating System**: Linux\n- **Compiler**: Clang\n- **Build flags**: `--with-thread-sanitizer --with-pydebug --enable-experimental-jit=yes --with-lto=full --with-tail-call-interp --disable-gil`\n\n### Additional Information\n\nA second similar data race is also reported for another write in `_structmodule_exec` at line 2746:33 to the same global variable.\n\nBoth races involve `InterpreterPoolExecutor` threads executing module initialization code concurrently in different subinterpreters.\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\nLinux\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-140909\n* gh-141501\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/ashm-dev","@type":"Person","name":"ashm-dev"},"datePublished":"2025-10-17T16:20:20.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/140260/cpython/issues/140260"}
| 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:7c4666c8-dae3-127f-9432-7054cd86ca40 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | B7CA:312517:193A90D:22E1A74:696AA40B |
| html-safe-nonce | 2d2810b73408c23332697a065b61a4ecd91614d3f708dbc9774acb43b8bc3839 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCN0NBOjMxMjUxNzoxOTNBOTBEOjIyRTFBNzQ6Njk2QUE0MEIiLCJ2aXNpdG9yX2lkIjoiMzg2MTkyNzg4MTU3NDM2MDA3NSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 80c7b44decf0cfe12197e9fb9ff96833d1e25b315119c211e67ed08bafaad4cc |
| hovercard-subject-tag | issue:3526748374 |
| 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/140260/issue_layout |
| twitter:image | https://opengraph.githubassets.com/1941addf031eecba6b9579162eef5028c00056d2f8b4b4d4d3de36c514fc209d/python/cpython/issues/140260 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/1941addf031eecba6b9579162eef5028c00056d2f8b4b4d4d3de36c514fc209d/python/cpython/issues/140260 |
| og:image:alt | Bug report Bug description: ThreadSanitizer detects a data race when using InterpreterPoolExecutor with the free-threading build. Multiple threads simultaneously write to the global variable lilend... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | ashm-dev |
| hostname | github.com |
| expected-hostname | github.com |
| None | a51f97dbb9326f71c08ecb61577457d543c602124d1a2672871258ef37ac5261 |
| 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 | 4bd0eac606c70914085176ef312ebdcd97a8cdf1 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width