|
1 | 1 | /* Wrap void * pointers to be passed between C modules */ |
2 | 2 |
|
3 | 3 | #include "Python.h" |
| 4 | +#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED() |
| 5 | +#include "pycore_object.h" // _PyObject_GC_TRACK() |
| 6 | + |
4 | 7 |
|
5 | 8 | /* Internal structure of PyCapsule */ |
6 | 9 | typedef struct { |
@@ -71,7 +74,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor) |
71 | 74 | capsule->destructor = destructor; |
72 | 75 | capsule->traverse_func = NULL; |
73 | 76 | capsule->clear_func = NULL; |
74 | | - // Only track the capsule if _PyCapsule_SetTraverse() is called |
| 77 | + // Only track the object by the GC when _PyCapsule_SetTraverse() is called |
75 | 78 |
|
76 | 79 | return (PyObject *)capsule; |
77 | 80 | } |
@@ -204,8 +207,14 @@ _PyCapsule_SetTraverse(PyObject *op, traverseproc traverse_func, inquiry clear_f |
204 | 207 | } |
205 | 208 | PyCapsule *capsule = (PyCapsule *)op; |
206 | 209 |
|
207 | | - if (!PyObject_GC_IsTracked(op)) { |
208 | | - PyObject_GC_Track(op); |
| 210 | + if (traverse_func == NULL || clear_func == NULL) { |
| 211 | + PyErr_SetString(PyExc_ValueError, |
| 212 | + "_PyCapsule_SetTraverse() called with NULL callback"); |
| 213 | + return -1; |
| 214 | + } |
| 215 | + |
| 216 | + if (!_PyObject_GC_IS_TRACKED(op)) { |
| 217 | + _PyObject_GC_TRACK(op); |
209 | 218 | } |
210 | 219 |
|
211 | 220 | capsule->traverse_func = traverse_func; |
@@ -306,24 +315,22 @@ capsule_repr(PyObject *o) |
306 | 315 | static int |
307 | 316 | capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg) |
308 | 317 | { |
309 | | - if (capsule->traverse_func) { |
310 | | - return capsule->traverse_func((PyObject*)capsule, visit, arg); |
311 | | - } |
312 | | - else { |
313 | | - return 0; |
314 | | - } |
| 318 | + // Capsule object is only tracked by the GC |
| 319 | + // if _PyCapsule_SetTraverse() is called |
| 320 | + assert(capsule->traverse_func != NULL); |
| 321 | + |
| 322 | + return capsule->traverse_func((PyObject*)capsule, visit, arg); |
315 | 323 | } |
316 | 324 |
|
317 | 325 |
|
318 | 326 | static int |
319 | 327 | capsule_clear(PyCapsule *capsule) |
320 | 328 | { |
321 | | - if (capsule->clear_func) { |
322 | | - return capsule->clear_func((PyObject*)capsule); |
323 | | - } |
324 | | - else { |
325 | | - return 0; |
326 | | - } |
| 329 | + // Capsule object is only tracked by the GC |
| 330 | + // if _PyCapsule_SetTraverse() is called |
| 331 | + assert(capsule->clear_func != NULL); |
| 332 | + |
| 333 | + return capsule->clear_func((PyObject*)capsule); |
327 | 334 | } |
328 | 335 |
|
329 | 336 |
|
|
0 commit comments