@@ -204,17 +204,32 @@ value must be in a particular range or must satisfy other conditions,
204204:c:data: `PyExc_ValueError ` is appropriate.
205205
206206You can also define a new exception that is unique to your module.
207- For this, you can declare a static global object variable at the beginning
208- of the file::
207+ The simplest way to do this is to declare a static global object variable at
208+ the beginning of the file::
209209
210- static PyObject *SpamError;
210+ static PyObject *SpamError = NULL ;
211211
212- and initialize it with an exception object in the module's
212+ and initialize it by calling :c:func: ` PyErr_NewException ` in the module's
213213:c:data: `Py_mod_exec ` function (:c:func: `!spam_module_exec `)::
214214
215+ SpamError = PyErr_NewException("spam.error", NULL, NULL);
216+
217+ Since :c:data: `!SpamError ` is a global variable, it will be overwitten every time
218+ the module is reinitialized, when the :c:data: `Py_mod_exec ` function is called.
219+
220+ For now, let's avoid the issue: we will block repeated initialization by raising an
221+ :py:exc: `ImportError `::
222+
223+ static PyObject *SpamError = NULL;
224+
215225 static int
216226 spam_module_exec(PyObject *m)
217227 {
228+ if (SpamError != NULL) {
229+ PyErr_SetString(PyExc_ImportError,
230+ "cannot initialize spam module more than once");
231+ return -1;
232+ }
218233 SpamError = PyErr_NewException("spam.error", NULL, NULL);
219234 if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
220235 return -1;
@@ -253,6 +268,11 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to
253268become a dangling pointer. Should it become a dangling pointer, C code which
254269raises the exception could cause a core dump or other unintended side effects.
255270
271+ For now, the :c:func: `Py_DECREF ` call to remove this reference is missing.
272+ Even when the Python interpreter shuts down, the global :c:data: `!SpamError `
273+ variable will not be garbage-collected. It will "leak".
274+ We did, however, ensure that this will happen at most once per process.
275+
256276We discuss the use of :c:macro: `PyMODINIT_FUNC ` as a function return type later in this
257277sample.
258278
0 commit comments