Title: C API: Design an API to disallow creating more than one extension instance per Python process · Issue #111088 · python/cpython · GitHub
Open Graph Title: C API: Design an API to disallow creating more than one extension instance per Python process · Issue #111088 · python/cpython
X Title: C API: Design an API to disallow creating more than one extension instance per Python process · Issue #111088 · python/cpython
Description: Somewhere in PyModuleDef, we should add a way to disallow globally the creation of more than one extension instance. Or maybe the restriction should be that an extension cannot be loaded in two different interpreters. Honestly, I'm not s...
Open Graph Description: Somewhere in PyModuleDef, we should add a way to disallow globally the creation of more than one extension instance. Or maybe the restriction should be that an extension cannot be loaded in two dif...
X Description: Somewhere in PyModuleDef, we should add a way to disallow globally the creation of more than one extension instance. Or maybe the restriction should be that an extension cannot be loaded in two dif...
Opengraph URL: https://github.com/python/cpython/issues/111088
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"C API: Design an API to disallow creating more than one extension instance per Python process","articleBody":"Somewhere in `PyModuleDef`, we should add a way to disallow globally the creation of more than one extension instance.\r\n\r\nOr maybe the restriction should be that an extension cannot be loaded in two different interpreters. Honestly, I'm not sure.\r\n\r\n@ericsnowcurrently no longer wants to treat the **main** interpreter differently: see issue gh-109857.\r\n\r\nPreviously, I proposed to directly expose PyInterpreterState_IsMain() to the limited C API, but the idea got rejected.\r\n\r\n---\r\n\r\nThe syslog module behaves differently if it's used in the **main interpreter**:\r\n\r\n```c\r\nstatic inline int\r\nis_main_interpreter(void)\r\n{\r\n return (PyInterpreterState_Get() == PyInterpreterState_Main());\r\n}\r\n\r\n...\r\n if (!is_main_interpreter()) {\r\n PyErr_SetString(PyExc_RuntimeError, \"subinterpreter can't use syslog.openlog()\");\r\n return NULL;\r\n }\r\n```\r\n\r\nThe syslog module stores a Python object in `static PyObject *S_ident_o = NULL;`. It's a way to keep a string passed to C openlog() function alive until closelog() is called. The problem is to decide which extension instance and/or which Python interpreter is responsible for that memory: the memory must be kept alive until closelog() is called. But what if each Python interpreter call openlog()? Calling openlog() more than once overrides the previous call. But if closelog() is called, if multiple interpreters called openlog(), you might think that syslog is still usable, whereas closelog() has been called.\r\n\r\nSee issue gh-99127 and PR gh-99128 which added `is_main_interpreter()` function to syslog.\r\n\r\n---\r\n\r\nCython already implements a similar, but different check: it raises **\"this module can only be loaded into one interpreter per process\"** error message.\r\n\r\nCython uses a different logic to handle PEP 489 \"Multi-phase extension module initialization\". It uses a ``static PY_INT64_T main_interpreter_id = -1;`` variable which is initialized at the first call of ``__Pyx_check_single_interpreter()``.\r\n\r\n```c\r\n//#if CYTHON_PEP489_MULTI_PHASE_INIT\r\nstatic CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) {\r\n #if PY_VERSION_HEX \u003e= 0x030700A1\r\n static PY_INT64_T main_interpreter_id = -1;\r\n PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()-\u003einterp);\r\n if (main_interpreter_id == -1) {\r\n main_interpreter_id = current_id;\r\n return (unlikely(current_id == -1)) ? -1 : 0;\r\n } else if (unlikely(main_interpreter_id != current_id))\r\n\r\n #else\r\n static PyInterpreterState *main_interpreter = NULL;\r\n PyInterpreterState *current_interpreter = PyThreadState_Get()-\u003einterp;\r\n if (!main_interpreter) {\r\n main_interpreter = current_interpreter;\r\n } else if (unlikely(main_interpreter != current_interpreter))\r\n #endif\r\n\r\n {\r\n PyErr_SetString(\r\n PyExc_ImportError,\r\n \"Interpreter change detected - this module can only be loaded into one interpreter per process.\");\r\n return -1;\r\n }\r\n return 0;\r\n}\r\n```","author":{"url":"https://github.com/vstinner","@type":"Person","name":"vstinner"},"datePublished":"2023-10-19T23:10:09.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/111088/cpython/issues/111088"}
| 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:d05f3a0d-3b73-f801-1ddb-6a064d34e66f |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8AA2:311995:836815:AA869C:696AF021 |
| html-safe-nonce | e1ec1156727aba28dfccf0c4a22f71be55e5d157c58c7a1aeed393d6dde4cc9d |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4QUEyOjMxMTk5NTo4MzY4MTU6QUE4NjlDOjY5NkFGMDIxIiwidmlzaXRvcl9pZCI6IjQzMDM4NTkyMjAxMDExMzIzMjEiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 493bc2e2bfcd4abbaaeb9e5b994c24e99c25f1817102d3cddf9f1f0026ded9a8 |
| hovercard-subject-tag | issue:1953190991 |
| 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/111088/issue_layout |
| twitter:image | https://opengraph.githubassets.com/7a1ef7719e3cbc757d0ae092906a98ec95de604bff2dd9259fa4ea4114ba10fd/python/cpython/issues/111088 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/7a1ef7719e3cbc757d0ae092906a98ec95de604bff2dd9259fa4ea4114ba10fd/python/cpython/issues/111088 |
| og:image:alt | Somewhere in PyModuleDef, we should add a way to disallow globally the creation of more than one extension instance. Or maybe the restriction should be that an extension cannot be loaded in two dif... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | vstinner |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f99f7c1d70f01da5b93e5ca90303359738944d8ab470e396496262c66e60b8d |
| 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 | 82560a55c6b2054555076f46e683151ee28a19bc |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width