Title: data races in decimal module with global context · Issue #141148 · python/cpython · GitHub
Open Graph Title: data races in decimal module with global context · Issue #141148 · python/cpython
X Title: data races in decimal module with global context · Issue #141148 · python/cpython
Description: Reproducer: import decimal from threading import Thread, Barrier context = decimal.Context() context.prec = 28 barrier = Barrier(10) def race(): barrier.wait() decimal.Decimal('1.0', context=context) if __name__ == "__main__": while True...
Open Graph Description: Reproducer: import decimal from threading import Thread, Barrier context = decimal.Context() context.prec = 28 barrier = Barrier(10) def race(): barrier.wait() decimal.Decimal('1.0', context=contex...
X Description: Reproducer: import decimal from threading import Thread, Barrier context = decimal.Context() context.prec = 28 barrier = Barrier(10) def race(): barrier.wait() decimal.Decimal('1.0', contex...
Opengraph URL: https://github.com/python/cpython/issues/141148
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"data races in decimal module with global context","articleBody":"Reproducer:\n```py\nimport decimal\nfrom threading import Thread, Barrier\n\ncontext = decimal.Context()\ncontext.prec = 28\n\nbarrier = Barrier(10)\n\ndef race():\n barrier.wait()\n decimal.Decimal('1.0', context=context)\n\nif __name__ == \"__main__\":\n while True:\n threads = [Thread(target=race) for _ in range(10)]\n for thread in threads:\n thread.start()\n for thread in threads:\n thread.join()\n```\n\nData race:\n```console\n==================\nWARNING: ThreadSanitizer: data race (pid=58514)\n Write of size 4 at 0x00010d315cbc by thread T5808:\n #0 dec_addstatus _decimal.c:612 (_decimal.cpython-315t-darwin.so:arm64+0x9a88)\n #1 PyDecType_FromCStringExact _decimal.c:2323 (_decimal.cpython-315t-darwin.so:arm64+0x1a4a4)\n #2 dec_new _decimal.c.h:572 (_decimal.cpython-315t-darwin.so:arm64+0x506c)\n #3 type_call typeobject.c:2432 (python.exe:arm64+0x10017e768)\n #4 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x10007eb64)\n #5 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x10007f750)\n #6 _PyEval_EvalFrameDefault generated_cases.c.h:1620 (python.exe:arm64+0x100277dec)\n #7 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #8 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #9 method_vectorcall classobject.c:65 (python.exe:arm64+0x100084190)\n #10 _PyObject_Call call.c:348 (python.exe:arm64+0x10007f8b0)\n #11 PyObject_Call call.c:373 (python.exe:arm64+0x10007f9d8)\n #12 _PyEval_EvalFrameDefault generated_cases.c.h:2616 (python.exe:arm64+0x10027bf64)\n #13 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #14 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #15 method_vectorcall classobject.c:73 (python.exe:arm64+0x10008422c)\n #16 context_run context.c:728 (python.exe:arm64+0x1002b53dc)\n #17 _PyEval_EvalFrameDefault generated_cases.c.h:3710 (python.exe:arm64+0x10027ffbc)\n #18 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #19 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #20 method_vectorcall classobject.c:73 (python.exe:arm64+0x10008422c)\n #21 _PyObject_Call call.c:348 (python.exe:arm64+0x10007f964)\n #22 PyObject_Call call.c:373 (python.exe:arm64+0x10007f9d8)\n #23 thread_run _threadmodule.c:387 (python.exe:arm64+0x10041b338)\n #24 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x100358824)\n\n Previous write of size 4 at 0x00010d315cbc by thread T5806:\n #0 dec_addstatus _decimal.c:612 (_decimal.cpython-315t-darwin.so:arm64+0x9a88)\n #1 PyDecType_FromCStringExact _decimal.c:2323 (_decimal.cpython-315t-darwin.so:arm64+0x1a4a4)\n #2 dec_new _decimal.c.h:572 (_decimal.cpython-315t-darwin.so:arm64+0x506c)\n #3 type_call typeobject.c:2432 (python.exe:arm64+0x10017e768)\n #4 _PyObject_MakeTpCall call.c:242 (python.exe:arm64+0x10007eb64)\n #5 PyObject_Vectorcall call.c:327 (python.exe:arm64+0x10007f750)\n #6 _PyEval_EvalFrameDefault generated_cases.c.h:1620 (python.exe:arm64+0x100277dec)\n #7 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #8 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #9 method_vectorcall classobject.c:65 (python.exe:arm64+0x100084190)\n #10 _PyObject_Call call.c:348 (python.exe:arm64+0x10007f8b0)\n #11 PyObject_Call call.c:373 (python.exe:arm64+0x10007f9d8)\n #12 _PyEval_EvalFrameDefault generated_cases.c.h:2616 (python.exe:arm64+0x10027bf64)\n #13 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #14 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #15 method_vectorcall classobject.c:73 (python.exe:arm64+0x10008422c)\n #16 context_run context.c:728 (python.exe:arm64+0x1002b53dc)\n #17 _PyEval_EvalFrameDefault generated_cases.c.h:3710 (python.exe:arm64+0x10027ffbc)\n #18 _PyEval_Vector ceval.c:1989 (python.exe:arm64+0x10026ad88)\n #19 _PyFunction_Vectorcall call.c (python.exe:arm64+0x10007fcec)\n #20 method_vectorcall classobject.c:73 (python.exe:arm64+0x10008422c)\n #21 _PyObject_Call call.c:348 (python.exe:arm64+0x10007f964)\n #22 PyObject_Call call.c:373 (python.exe:arm64+0x10007f9d8)\n #23 thread_run _threadmodule.c:387 (python.exe:arm64+0x10041b338)\n #24 pythread_wrapper thread_pthread.h:234 (python.exe:arm64+0x100358824)\nSUMMARY: ThreadSanitizer: data race _decimal.c:615 in dec_addstatus\n==================\n```\n\nI discovered this while adding thread safety support to [msgspec](https://github.com/jcrist/msgspec). Running its test suite under pytest-run-parallel leads to similar data races as present above from the minimal reproducer. \n\nSee https://gist.github.com/kumaraditya303/3c26f31eaf0beea39d7eeb539b662846 for full tsan report\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-146482\n* gh-151953\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/kumaraditya303","@type":"Person","name":"kumaraditya303"},"datePublished":"2025-11-06T14:54:31.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":16},"url":"https://github.com/141148/cpython/issues/141148"}
| 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:f2d028c2-c6fa-26e5-8cb7-1b014f1a1a6a |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | D640:22A236:77DF3:A1CC7:6A532A90 |
| html-safe-nonce | 582663e673b7cf419e92858413f0579ef816993781bbdcfd4f139b68e3a4a693 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENjQwOjIyQTIzNjo3N0RGMzpBMUNDNzo2QTUzMkE5MCIsInZpc2l0b3JfaWQiOiI2MTQwMDM5MTg4OTE2MTUyOTc2IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 80e11343d8c8ebfe038e8570f28e2144b0413a78aea92e85c1cf1fa9c90cbc17 |
| hovercard-subject-tag | issue:3596171795 |
| 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/141148/issue_layout |
| twitter:image | https://opengraph.githubassets.com/80a521ec9b56f6cf6148ea1d88ace36d7f9f530e0f594dc9152e85f9faab9999/python/cpython/issues/141148 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/80a521ec9b56f6cf6148ea1d88ace36d7f9f530e0f594dc9152e85f9faab9999/python/cpython/issues/141148 |
| og:image:alt | Reproducer: import decimal from threading import Thread, Barrier context = decimal.Context() context.prec = 28 barrier = Barrier(10) def race(): barrier.wait() decimal.Decimal('1.0', context=contex... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | kumaraditya303 |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| 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 | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width