From 938bb6e3063420ed3b406cddee8f76495827f7e7 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 17 May 2025 14:36:37 +0200 Subject: [PATCH 1/2] Isolating HOWTO, opt-out: Add notes on nogil & reinit --- Doc/howto/isolating-extensions.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst index a636e06bda8344..a73325ccca55f2 100644 --- a/Doc/howto/isolating-extensions.rst +++ b/Doc/howto/isolating-extensions.rst @@ -215,21 +215,36 @@ multiple interpreters correctly. If this is not yet the case for your module, you can explicitly make your module loadable only once per process. For example:: + // A process-wide flag static int loaded = 0; + // Mutex to provide thread safety (only needed for free-threaded Python) + static PyMutex modinit_mutex = {0}; + static int exec_module(PyObject* module) { + PyMutex_Lock(modinit_mutex); if (loaded) { + PyMutex_Unlock(modinit_mutex); PyErr_SetString(PyExc_ImportError, "cannot load module more than once per process"); return -1; } loaded = 1; + PyMutex_Unlock(modinit_mutex); // ... rest of initialization } +If your module's :c:member:`PyModuleDef.m_clear` function is able to prepare +for future re-initialization, it should clear the ``loaded`` flag. +In this case, your module won't support multiple instances existing +*concurrently*, but it will, for example, support being loaded after +Python runtime shutdown (:c:func:`Py_FinalizeEx`) and re-initialization +(:c:func:`Py_Initialize`). + + Module State Access from Functions ---------------------------------- From 24b1e2c3847466878120cc97d5c0d395dd75cb04 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 17 May 2025 17:27:43 +0200 Subject: [PATCH 2/2] Add & --- Doc/howto/isolating-extensions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/howto/isolating-extensions.rst b/Doc/howto/isolating-extensions.rst index a73325ccca55f2..5513cd7367519f 100644 --- a/Doc/howto/isolating-extensions.rst +++ b/Doc/howto/isolating-extensions.rst @@ -224,15 +224,15 @@ process. For example:: static int exec_module(PyObject* module) { - PyMutex_Lock(modinit_mutex); + PyMutex_Lock(&modinit_mutex); if (loaded) { - PyMutex_Unlock(modinit_mutex); + PyMutex_Unlock(&modinit_mutex); PyErr_SetString(PyExc_ImportError, "cannot load module more than once per process"); return -1; } loaded = 1; - PyMutex_Unlock(modinit_mutex); + PyMutex_Unlock(&modinit_mutex); // ... rest of initialization }