@@ -204,17 +204,32 @@ value must be in a particular range or must satisfy other conditions,
204
204
:c:data: `PyExc_ValueError ` is appropriate.
205
205
206
206
You 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::
209
209
210
- static PyObject *SpamError;
210
+ static PyObject *SpamError = NULL ;
211
211
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
213
213
:c:data: `Py_mod_exec ` function (:c:func: `!spam_module_exec `)::
214
214
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
+
215
225
static int
216
226
spam_module_exec(PyObject *m)
217
227
{
228
+ if (SpamError != NULL) {
229
+ PyErr_SetString(PyExc_ImportError,
230
+ "cannot initialize spam module more than once");
231
+ return -1;
232
+ }
218
233
SpamError = PyErr_NewException("spam.error", NULL, NULL);
219
234
if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
220
235
return -1;
@@ -253,6 +268,11 @@ needed to ensure that it will not be discarded, causing :c:data:`!SpamError` to
253
268
become a dangling pointer. Should it become a dangling pointer, C code which
254
269
raises the exception could cause a core dump or other unintended side effects.
255
270
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
+
256
276
We discuss the use of :c:macro: `PyMODINIT_FUNC ` as a function return type later in this
257
277
sample.
258
278
0 commit comments