https://github.com/python/cpython/commit/998cedb9bc6b37930d50fa7eca7e2ddf35b433b2 commit: 998cedb9bc6b37930d50fa7eca7e2ddf35b433b2 branch: 3.14 author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com> committer: AA-Turner <9087854+aa-tur...@users.noreply.github.com> date: 2025-05-28T07:58:49Z summary:
[3.14] gh-134160: Block multiple module initialization (GH-134773) (#134827) gh-134160: Block multiple module initialization (GH-134773) (cherry picked from commit 469a56470b1d8df03862d8ceb73aebca14772dcf) Co-authored-by: Petr Viktorin <encu...@gmail.com> Co-authored-by: Adam Turner <9087854+aa-tur...@users.noreply.github.com> files: M Doc/extending/extending.rst diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst index 918c751b009761..fd63495674651b 100644 --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -204,17 +204,32 @@ value must be in a particular range or must satisfy other conditions, :c:data:`PyExc_ValueError` is appropriate. You can also define a new exception that is unique to your module. -For this, you can declare a static global object variable at the beginning -of the file:: +The simplest way to do this is to declare a static global object variable at +the beginning of the file:: - static PyObject *SpamError; + static PyObject *SpamError = NULL; -and initialize it with an exception object in the module's +and initialize it by calling :c:func:`PyErr_NewException` in the module's :c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`):: + SpamError = PyErr_NewException("spam.error", NULL, NULL); + +Since :c:data:`!SpamError` is a global variable, it will be overwitten every time +the module is reinitialized, when the :c:data:`Py_mod_exec` function is called. + +For now, let's avoid the issue: we will block repeated initialization by raising an +:py:exc:`ImportError`:: + + static PyObject *SpamError = NULL; + static int spam_module_exec(PyObject *m) { + if (SpamError != NULL) { + PyErr_SetString(PyExc_ImportError, + "cannot initialize spam module more than once"); + return -1; + } SpamError = PyErr_NewException("spam.error", NULL, NULL); if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) { return -1; @@ -253,6 +268,11 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to become a dangling pointer. Should it become a dangling pointer, C code which raises the exception could cause a core dump or other unintended side effects. +For now, the :c:func:`Py_DECREF` call to remove this reference is missing. +Even when the Python interpreter shuts down, the global :c:data:`!SpamError` +variable will not be garbage-collected. It will "leak". +We did, however, ensure that this will happen at most once per process. + We discuss the use of :c:macro:`PyMODINIT_FUNC` as a function return type later in this sample. _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: arch...@mail-archive.com